Skip to content

LSP diagnostics waits hardcoded at 5s/10s: slow servers return no diagnostics, indistinguishable from a clean file #41218

Description

@Yagi-Michael

Summary

The diagnostics wait timeouts in packages/opencode/src/lsp/client.ts are hardcoded at 5s (document) and 10s (full). For language servers that need longer to parse a translation unit, the client always gives up first and returns no diagnostics — which is indistinguishable from "the file is clean".

This is a correctness problem rather than a performance one: an agent consuming the LSP cannot tell "no problems found" from "we stopped waiting", so it reports false confidence or stops trusting the tool.

// packages/opencode/src/lsp/client.ts:14-15
const DIAGNOSTICS_DOCUMENT_WAIT_TIMEOUT_MS = 5_000
const DIAGNOSTICS_FULL_WAIT_TIMEOUT_MS = 10_000

Environment

  • opencode 1.18.4 (also reproduced against dev @ 284214c)
  • clangd 21.1.8, Linux x64
  • Unreal Engine 5 game project, 23,382-entry compile_commands.json

Reproduction

Any C++ file in a large Unreal project. One translation unit pulls in ~3,764 transitive headers, and clangd needs roughly 20s to parse it — measured directly over stdio LSP, independent of opencode:

query time
first open of a UE file (cold) 19–25s
same file again, still open 0.00s
a sibling file in the same module 19.03s

Against opencode:

$ opencode debug lsp diagnostics /path/to/HGGameUserSettings.cpp
{
  "/path/to/.clangd": []
}

The requested file is absent from the result entirely, after ~11s — consistent with 5s + 10s. The same file checked with the real compiler (clang++ -fsyntax-only, using the flags from compile_commands.json) compiles cleanly, and a deliberately broken variant reports its error correctly, so clangd and the configuration are both fine.

Not caused by configuration

Ruled out by measurement:

  • Compile database staleness — 442 of 452 files present; clangd interpolates flags for the rest and returns correct symbols.
  • Database size — scoping it 8.5× (23,382 → 2,741 entries) moved parse time only 27.1s → 24.5s.
  • .clangd force-include — removing it gives 14.2s → 10.5s and reintroduces 82 false errors. Still at the threshold.
  • --pch-storage=memory — no change (13.9s).

There is no configuration option to extend the wait.

Related

Suggested fix

Make the two waits configurable per LSP server, defaulting to the current constants so nothing changes for anyone who doesn't opt in:

"lsp": {
  "clangd": {
    "command": ["clangd", "--compile-commands-dir=..."],
    "timeout": { "document": 60000, "full": 120000 }
  }
}

With that applied locally, the same command returns the real diagnostic in 13s:

Error [3:13] Use of undeclared identifier 'this_symbol_does_not_exist'

I have a working patch (~35 lines across 5 files) and am happy to open a PR against this issue.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions