neoclide/coc.nvim · warning · Error
Empty symbols returned from language server.
Error message
Empty symbols returned from language server.
What it means
Thrown when buf.getSymbols() returns undefined/null or an empty array from the language server's textDocument/documentSymbol request. The comment in the source explains this is deliberate: servers may briefly return empty symbol lists right after buffer initialization, so the error forces the tree view to reload rather than rendering a permanently empty outline.
Source
Thrown at src/handler/symbols/outline.ts:198
let provider = new BasicDataProvider({
expandLevel: this.config.expandLevel,
provideData: async () => {
let buf = this.buffers.getItem(bufnr)
if (!buf) throw new Error('Document not attached')
let doc = workspace.getDocument(bufnr)
if (!languages.hasProvider(ProviderName.DocumentSymbol, doc.textDocument)) {
throw new Error('Document symbol provider not found')
}
let meta = languages.getDocumentSymbolMetadata(doc.textDocument)
if (meta && meta.label) {
let views = this.treeViewList.filter(v => v.valid && v.targetBufnr == bufnr)
views.forEach(view => view.description = meta.label)
}
this.setMessage(bufnr, 'Loading document symbols')
let arr = await buf.getSymbols()
if (!arr || arr.length == 0) {
// server may return empty symbols on buffer initialize, throw error to force reload.
throw new Error('Empty symbols returned from language server. ')
}
this.setMessage(bufnr, undefined)
return this.convertSymbols(bufnr, arr)
},
handleClick: async item => {
let winnr = await nvim.call('bufwinnr', [bufnr])
if (winnr == -1) return
nvim.pauseNotification()
nvim.command(`${winnr}wincmd w`, true)
let pos = item.selectRange.start
nvim.call('coc#cursor#move_to', [pos.line, pos.character], true)
nvim.command(`normal! zz`, true)
let buf = nvim.createBuffer(bufnr)
buf.highlightRanges('outline-hover', 'CocHoverRange', [item.selectRange])
nvim.command('redraw', true)
await nvim.resumeNotification()
setTimeout(() => {
buf.clearNamespace('outline-hover')View on GitHub (pinned to 50e974d969)
Solutions
- Simply reload/refresh the outline — the throw exists to trigger a reload once symbols become available.
- Wait for the server to finish indexing (check :CocCommand workspace.showOutput or server status).
- Verify the server actually returns symbols (query it with :CocCommand documentSymbols in the same buffer).
- If it consistently returns empty, the server lacks documentSymbol support — switch servers or accept a non-outline filetype.
Defensive patterns
Strategy: retry
Try / catch
for (let i = 0; i < 3; i++) {
try {
await outline.show(bufnr)
break
} catch (e) {
if (String(e).includes('Empty symbols')) {
await new Promise(r => setTimeout(r, 500)) // server still indexing
continue
}
throw e
}
} Prevention
- Delay outline opening until the server reports ready/indexing complete.
- Retry on this error — the throw is deliberately used to trigger a reload.
- Check the server actually returns symbols via :CocCommand documentSymbols.
- Use servers known to implement documentSymbol for your language.
When it happens
Trigger: Opening :CocOutline while the server is still analyzing the file; the document genuinely has no symbols; the server returns an empty result for documentSymbol (unsupported or an indexing race); the file is empty or contains only comments in some servers.
Common situations: Outline opened immediately after file open on slow servers (rust-analyzer, clangd cold start); huge files not yet fully indexed; servers that return empty instead of null for symbol-less documents; transient server hiccup mid-request.
Related errors
- Document symbol provider not found
- ${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/171be91cfd477073.
Report an issue: GitHub.