{"record":{"id":"11105d836e2ed6e7","repo":"neoclide/coc.nvim","slug":"client-is-not-running-and-can-t-be-stopped-its-cu","errorCode":null,"errorMessage":"Client is not running and can't be stopped. Its current state is: ${this.$state}","messagePattern":"Client is not running and can't be stopped\\. Its current state is: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/language-client/client.ts","lineNumber":1351,"sourceCode":"\n  protected async shutdown(mode: ShutdownMode, timeout: number): Promise<void> {\n    // If the client is stopped or in its initial state return.\n    if (this.$state === ClientState.Stopped || this.$state === ClientState.Initial) {\n      return\n    }\n    if (this.$state === ClientState.Starting && this._onStart) {\n      await this._onStart\n    }\n    // If we are stopping the client and have a stop promise return it.\n    if (this.$state === ClientState.Stopping) {\n      return this._onStop\n    }\n\n    const connection = this._connection\n    // We can't stop a client that is not running (e.g. has no connection). Especially not\n    // on that us starting since it can't be correctly synchronized.\n    if (connection === undefined || (this.$state !== ClientState.Running && this.$state !== ClientState.StartFailed)) {\n      throw new Error(`Client is not running and can't be stopped. Its current state is: ${this.$state}`)\n    }\n    this._initializeResult = undefined\n    this.$state = ClientState.Stopping\n    this.cleanUp(mode)\n\n    let tm: NodeJS.Timeout\n    const tp = new Promise<any>(c => { tm = setTimeout(c, timeout) })\n    const shutdown = (async connection => {\n      await connection.shutdown()\n      await connection.exit()\n      return connection\n    })(connection)\n    // If the connection closes while the shutdown is in flight (e.g. the\n    // server crashed), handleConnectionClosed signals it here so the stop\n    // completes successfully: the server is gone, which is the outcome the\n    // caller asked for. Without this, the pending shutdown rejects after the\n    // connection is disposed, reporting a false stop failure.\n    const close = new Promise<Connection>(resolve => {","sourceCodeStart":1333,"sourceCodeEnd":1369,"githubUrl":"https://github.com/neoclide/coc.nvim/blob/50e974d9692461a69147d5cab146a8d3e439abe4/src/language-client/client.ts#L1333-L1369","documentation":"LanguageClient.stop() throws this when the client has no active connection or its state is neither Running nor StartFailed. Clients mid-start, already stopped/disposed, or stopping cannot be stopped again — the state machine forbids it to keep async shutdown synchronized.","triggerScenarios":"Calling client.stop() before start() ever completed (state is New/Starting); calling stop() twice (second call hits Stopping/Stopped state); stop() racing with a still-pending _start(); stop() after dispose already completed.","commonSituations":"Autocommands (VimLeave, BufUnload) firing stop on a never-started server; extensions stopping a client whose start is still awaiting the server handshake; double shutdown paths (coc shutdown + extension dispose both calling stop); watchdogs stopping clients during initialization timeouts.","solutions":["Guard stop() with client state — only call it when the client is running (or track a started flag in your code).","Await start() completion before allowing stop paths to run; cancel pending starts first.","Make stop idempotent in your code (catch and ignore this error).","If the state is permanently wedged, use :CocRestart or rebuild the client instance."],"exampleFix":"// before\nclient.stop() // may throw if never started\n\n// after\ntry {\n  await client.stop()\n} catch (e) {\n  // ignore: client not running (never started or already stopped)\n}","handlingStrategy":"try-catch","validationCode":"// only stop clients you previously started successfully\nlet started = false\nconst start = async () => { await client.start(); started = true }\nconst stop = async () => { if (started) await client.stop(); started = false }","typeGuard":null,"tryCatchPattern":"try {\n  await client.stop()\n} catch (e) {\n  // ignore: client not running (never started, stopping, or already stopped)\n}","preventionTips":["Track whether a client was successfully started before calling stop().","Make shutdown handlers (VimLeave, dispose) idempotent by catching this error.","Never call stop() while start() is still pending — await it first.","Rely on coc's own shutdown paths (:CocRestart / quit) rather than manual stop in autocmds."],"tags":["language-client","lifecycle","state-machine","lsp"],"backgroundTag":"client-not-running-cannot-stop","analyzedSha":"50e974d9692461a69147d5cab146a8d3e439abe4","analyzedAt":"2026-08-31T11:17:23.966Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}