Rust-analyzer causing freeze on quit in neovim

I've had this problem for a while now and am really hoping to find some help here. When I try to exit neovim with any of the usual commands (:q, :wq, wqa!, etc), nvim freezes and does not unfreeze until I exit the containing terminal. This only happens when I have enabled rust-analyzer.

I've removed almost all of the plugins I use, until I was just down to "hrsh7th/cmp-nvim-lsp", its dependencies, and "neovim/nvim-lspiconfig".

I've noticed that this only happens once I have added dependencies to a new project, and nvim exits normally before any crates are added.

I've tried:

  • using different terminals: xterm and alacritty
  • using different package managers: lazy.nvim and packer
  • using and removing rust-tools
  • updating rust with "rustup update"
  • deleting and then adding rust-analyzer

Now I'm all out of ideas and kind of pulling my hair out. I've taken a :LspLog of the last time I had to force quit a rust file pasted below, if that is informative to anyone.

Please help!

[INFO][2023-07-16 16:11:43] .../lua/vim/lsp.lua:1876 "exit_handler" { { _on_attach = <function 1>, attached_buffers = { true }, cancel_request = <function 2>, commands = {}, config = { _on_attach = <function 3>, autostart = true, capabilities = { experimental = { serverStatusNotification = true }, textDocument = { callHierarchy = { dynamicRegistration = false }, codeAction = { codeActionLiteralSupport = { codeActionKind = { valueSet = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" } } }, dataSupport = true, dynamicRegistration = false, isPreferredSupport = true, resolveSupport = { properties = { "edit" } } }, completion = { completionItem = { commitCharactersSupport = false, deprecatedSupport = false, documentationFormat = { "markdown", "plaintext" }, preselectSupport = false, snippetSupport = false }, completionItemKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 } }, contextSupport = false, dynamicRegistration = false }, declaration = { linkSupport = true }, definition = { linkSupport = true }, documentHighlight = { dynamicRegistration = false }, documentSymbol = { dynamicRegistration = false, hierarchicalDocumentSymbolSupport = true, symbolKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } } }, hover = { contentFormat = { "markdown", "plaintext" }, dynamicRegistration = false }, implementation = { linkSupport = true }, publishDiagnostics = { relatedInformation = true, tagSupport = { valueSet = { 1, 2 } } }, references = { dynamicRegistration = false }, rename = { dynamicRegistration = false, prepareSupport = true }, semanticTokens = { augmentsSyntaxTokens = true, dynamicRegistration = false, formats = { "relative" }, multilineTokenSupport = false, overlappingTokenSupport = true, requests = { full = { delta = true }, range = false }, serverCancelSupport = false, tokenModifiers = { "declaration", "definition", "readonly", "static", "deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary" }, tokenTypes = { "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", "parameter", "variable", "property", "enumMember", "event", "function", "method", "macro", "keyword", "modifier", "comment", "string", "number", "regexp", "operator", "decorator" } }, signatureHelp = { dynamicRegistration = false, signatureInformation = { activeParameterSupport = true, documentationFormat = { "markdown", "plaintext" }, parameterInformation = { labelOffsetSupport = true } } }, synchronization = { didSave = true, dynamicRegistration = false, willSave = true, willSaveWaitUntil = true }, typeDefinition = { linkSupport = true } }, window = { showDocument = { support = true }, showMessage = { messageActionItem = { additionalPropertiesSupport = false } }, workDoneProgress = true }, workspace = { applyEdit = true, configuration = true, didChangeWatchedFiles = { dynamicRegistration = true, relativePatternSupport = true }, semanticTokens = { refreshSupport = true }, symbol = { dynamicRegistration = false, hierarchicalWorkspaceSymbolSupport = true, symbolKind = { valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 } } }, workspaceEdit = { resourceOperations = { "rename", "create", "delete" } }, workspaceFolders = true } }, cmd = { "/home/brasides/.cargo/bin/rust-analyzer" }, cmd_cwd = "/home/brasides/programming/games/test_error", filetypes = { "rust" }, flags = {}, get_language_id = <function 4>, handlers = <1>{}, init_options = vim.empty_dict(), log_level = 2, message_level = 2, name = "rust_analyzer", on_attach = <function 5>, on_exit = <function 6>, on_init = <function 7>, root_dir = "/home/brasides/programming/games/test_error", settings = { ["rust-analyzer"] = { cargo = { buildScripts = { enable = true } }, imports = { granularity = { group = "module" }, prefix = "self" }, procMacro = { enable = true } } }, workspace_folders = <2>{ { name = "/home/brasides/programming/games/test_error", uri = "file:///home/brasides/programming/games/test_error" } }, = <3>{ __tostring = <function 8> } }, handlers = <table 1>, id = 1, initialized = true, is_stopped = <function 9>, messages = { messages = {}, name = "rust_analyzer", progress = { ["rust-analyzer/flycheck/0"] = { cancellable = true, done = true, title = "cargo check" }, ["rustAnalyzer/Fetching"] = { cancellable = false, done = true, title = "Fetching" }, ["rustAnalyzer/Indexing"] = { cancellable = false, message = "5/6 (bevy)", percentage = 83, title = "Indexing" }, ["rustAnalyzer/Loading"] = { cancellable = false, done = true, title = "Loading" }, ["rustAnalyzer/Roots Scanned"] = { cancellable = false, done = true, message = "235/235", percentage = 99, title = "Roots Scanned" } }, status = {} }, name = "rust_analyzer", notify = <function 10>, offset_encoding = "utf-16", request = <function 11>, request_sync = <function 12>, requests = { [5] = { bufnr = 1, method = "textDocument/semanticTokens/full/delta", type = "pending" } }, rpc = { is_closing = <function 13>, notify = <function 14>, request = <function 15>, terminate = <function 16> }, server_capabilities = { callHierarchyProvider = true, codeActionProvider = { codeActionKinds = { "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite" }, resolveProvider = true }, codeLensProvider = { resolveProvider = true }, completionProvider = { completionItem = { labelDetailsSupport = false }, triggerCharacters = { ":", ".", "'", "(" } }, declarationProvider = true, definitionProvider = true, documentFormattingProvider = true, documentHighlightProvider = true, documentOnTypeFormattingProvider = { firstTriggerCharacter = "=", moreTriggerCharacter = { ".", ">", "{" } }, documentRangeFormattingProvider = false, documentSymbolProvider = true, experimental = { externalDocs = true, hoverRange = true, joinLines = true, matchingBrace = true, moveItem = true, onEnter = true, openCargoToml = true, parentModule = true, runnables = { kinds = { "cargo" } }, ssr = true, workspaceSymbolScopeKindFiltering = true }, foldingRangeProvider = true, hoverProvider = true, implementationProvider = true, inlayHintProvider = { resolveProvider = true }, positionEncoding = "utf-16", referencesProvider = true, renameProvider = { prepareProvider = true }, selectionRangeProvider = true, semanticTokensProvider = { full = { delta = true }, legend = { tokenModifiers = { "documentation", "declaration", "static", "defaultLibrary", "async", "attribute", "callable", "constant", "consuming", "controlFlow", "crateRoot", "injected", "intraDocLink", "library", "mutable", "public", "reference", "trait", "unsafe" }, tokenTypes = { "comment", "decorator", "enumMember", "enum", "function", "interface", "keyword", "macro", "method", "namespace", "number", "operator", "parameter", "property", "string", "struct", "typeParameter", "variable", "angle", "arithmetic", "attribute", "attributeBracket", "bitwise", "boolean", "brace", "bracket", "builtinAttribute", "builtinType", "character", "colon", "comma", "comparison", "constParameter", "derive", "deriveHelper", "dot", "escapeSequence", "formatSpecifier", "generic", "label", "lifetime", "logical", "macroBang", "parenthesis", "punctuation", "selfKeyword", "selfTypeKeyword", "semicolon", "typeAlias", "toolModule", "union", "unresolvedReference" } }, range = true }, signatureHelpProvider = { triggerCharacters = { "(", ",", "<" } }, textDocumentSync = { change = 2, openClose = true, save = vim.empty_dict() }, typeDefinitionProvider = true, workspace = { fileOperations = { willRename = { filters = { { pattern = { glob = "/*.rs", matches = "file" }, scheme = "file" }, { pattern = { glob = "", matches = "folder" }, scheme = "file" } } } }, workspaceFolders = { changeNotifications = true, supported = true } }, workspaceSymbolProvider = true }, stop = <function 17>, supports_method = <function 18>, workspace_did_change_configuration = <function 19>, workspace_folders = <table 2> } }

Do you have autocmds like bufwrite or something?

Or what if you make a minimum config only containing ones related to RA. E.g

nvim -u NONE +":so min-config.lua"
-- min-config.lua
vim.cmd [[
  :set rtp+='/path/to/some/plugin'
]]

-- plugin setup

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.