neoclide/coc.nvim · error
Language server ${id} not found
Error message
Language server ${id} not found What it means
getLanguageClient resolves the LanguageClient backing a language service. If the service is still missing after waiting 100ms for extension activation, or exists but has no client yet, it throws. This usually means the language server was never registered or is still initializing.
Source
Thrown at src/services.ts:275
}
private registerClientsByConfig(lspConfig: { [key: string]: LanguageServerConfig }, folder?: URI): void {
for (let key of Object.keys(toObject(lspConfig))) {
let config: LanguageServerConfig = lspConfig[key]
if (!isValidServerConfig(key, config)) {
continue
}
this.registerLanguageClient(key, config, folder)
}
}
private async getLanguageClient(id: string): Promise<LanguageClient> {
let service = this.getService(id)
// wait for extension activate
if (!service) await wait(100)
service = this.getService(id)
if (!service || !service.client) {
throw new Error(`Language server ${id} not found`)
}
return service.client
}
/**
* @internal
*/
public async sendNotification(id: string, method: string, params?: any): Promise<void> {
let client = await this.getLanguageClient(id)
await Promise.resolve(client.sendNotification(method, params))
}
/**
* @internal
*/
public async sendRequest(id: string, method: string, params?: any, token?: CancellationToken): Promise<any> {
let client = await this.getLanguageClient(id)
token = token ?? CancellationToken.NoneView on GitHub (pinned to 50e974d969)
Solutions
- Confirm the id matches a registered language service.
- Wait for service state to become Running before requesting the client (poll state or listen to service events).
- Check the language extension is installed and activated for the buffer's filetype.
- Inspect service.start failure logs if the client never attaches.
Example fix
// before
let client = await services.getLanguageClient('tsserver')
// after
let service = services.getService('tsserver')
if (!service || service.state !== ServiceStat.Running) return
let client = await services.getLanguageClient('tsserver') Defensive patterns
Strategy: retry
Validate before calling
let service = services.getService(id) if (!service || service.state !== ServiceStat.Running) return null
Type guard
function hasClient(id: string): boolean {
let s = services.getService(id)
return s != null && s.client != null
} Try / catch
try {
return await services.getLanguageClient(id)
} catch (e) {
logger.warn(`client for ${id} unavailable: ${e.message}`)
return null
} Prevention
- Wait for the service to reach Running state before requesting the client.
- Don't call client accessors in autocmds that can fire before activation.
- Install/enable the language extension for relevant filetypes.
- Check server spawn logs if the client never attaches.
When it happens
Trigger: Calling services.getLanguageClient(id) (or the client accessor) before the language extension activates, or for a service created without a client, or with a wrong id.
Common situations: Vimrc/autocmd triggers a request on FileType before coc completes extension activation; server failed to spawn leaving service without a client.
Related errors
- Unsupported position encoding (${result.capabilities.positio
- ${uri} changed before apply edit
- Unable to getCallHierarchyItem at current position
- Action "${action.title}" is disabled: ${action.disabled.reas
- Format provider not found for buffer: ${doc.bufnr}
AI-assisted analysis of neoclide/coc.nvim@50e974d969 (2026-08-31).
Data as JSON: /api/errors/8907070897c8df12.
Report an issue: GitHub.