LSP tool: first query in a session returns incomplete results (cold-index race with server's initial workspace indexing)
Summary
The built-in LSP tool can return incomplete results for the first symbol query in a session. It sends the request (textDocument/references, call hierarchy, etc.) to the backing language server before that server has finished its initial workspace index, so the first query returns only the declaration (n=1) instead of the full result set. Roughly 500 ms later, the identical query returns the complete set.
Environment
- Claude Code: unknown
- OS: macOS (darwin/arm64), Node 24.18
- Language servers via a plugin
lspServersentry:basedpyright-langserver --stdio(Python),vtsls --stdio(TypeScript)
Reproduction
- Configure basedpyright and/or vtsls through a plugin's
lspServers. - In a fresh session, target a workspace where a symbol (
hub) has 180 call sites across 60 files. - As the first LSP action, run
LSPfindReferences(orincomingCalls) onhub. - Cold result: 1 reference (the declaration only).
- Re-run the identical query → 241 references across 61 files (complete).
Deterministic measurement
A standalone zero-dependency LSP stdio client reproduces this at the protocol level, isolating it from the agent:
- Query at 0 ms settle after server start → n=1
- Query at >=500 ms → complete (241), stable thereafter
- Behavior is binary (either n=1 or complete — no partial counts) and identical for basedpyright and vtsls.
- basedpyright's
diagnosticMode: "workspace"has no effect on the race.
Root cause
The tool issues the query before the server signals initial-index completion — there is no wait on $/progress / workDoneProgress end (or an equivalent server-ready signal) before returning the first result.
Impact
An agent that trusts the first result acts on incomplete references / call-hierarchy / impact data. The only current mitigation is behavioral — re-query when the result looks thin — which depends on the agent noticing.
Proposed fix
Before returning results for a query issued shortly after server start, have the LSP tool either:
- Await the server's initial workspace-index signal (
$/progressworkDoneProgress end, or a server-specific ready notification), or - Apply a bounded "retry until stable" — re-issue the query once if the first result returns within N ms of server start and the count changed — eliminating the race with negligible latency.
Optionally, expose a per-server settle / waitForIndex key in the lspServers config so users can opt in explicitly.