Summary
When an LSP server binary is on PATH but the session cwd has no resolvable TypeScript installation, typescript-language-server rejects initialize and exits — and the failure surfaces as a Bun source code-frame dump, repeated on every file read/edit/write for the rest of the session.
Reproduction
Start a session in any directory with a package.json/tsconfig.json marker but no resolvable tsserver.js, then edit a .ts file. Common triggers:
- Fresh
git worktree add directories without node_modules (the main trigger reported: worktrees at ~/.ao/data/worktrees/**)
- Projects pinning TypeScript 7 (native preview), whose package ships no
lib/tsserver.js at all — even with node_modules fully installed
Observed output (TUI):
LSP file sync failed: 376801 | client.messageBuffer = remaining;
376802 | if ("id" in message && message.id !== undefined) {
376803 | const pending2 = client.pendingRequests.get(message.id);
376804 | if (pending2) {
376805 | client.pendingRequests.delete(message.id);
376806 | pending2.reject(new Error(`LSP error: ${message.error.message}`));
^
error: LSP error: Request initialize failed with message: Could not find a valid TypeScript installation. Please ensure that the "typescript" dependency is installed in the workspace or that a valid `tsserver.path` is specified. Exiting.
at startMessageReader2 (/$bunfs/root/kimchi:376806:31)
Root cause
- The server answers
initialize with a JSON-RPC error; the rejection is constructed inside the message reader (src/extensions/lsp/client.ts, the pending.reject(new Error(\LSP error: ...`))` line — bundle line 376806 above).
- The
tool_result handler in src/extensions/lsp.ts logs the whole Error object (console.error("LSP file sync failed:", err)), so Bun renders the error together with its bundled-source code frame.
- The failed client is discarded from the client map, so the next
tool_result calls getOrCreateClient again — re-spawning the doomed server and re-dumping the frame on every file operation.
Expected behavior
One human-readable line per session (no code frame), a visible degraded status, and no re-spawn attempts until the next session.
Summary
When an LSP server binary is on PATH but the session cwd has no resolvable TypeScript installation,
typescript-language-serverrejectsinitializeand exits — and the failure surfaces as a Bun source code-frame dump, repeated on every file read/edit/write for the rest of the session.Reproduction
Start a session in any directory with a
package.json/tsconfig.jsonmarker but no resolvabletsserver.js, then edit a.tsfile. Common triggers:git worktree adddirectories withoutnode_modules(the main trigger reported: worktrees at~/.ao/data/worktrees/**)lib/tsserver.jsat all — even withnode_modulesfully installedObserved output (TUI):
Root cause
initializewith a JSON-RPC error; the rejection is constructed inside the message reader (src/extensions/lsp/client.ts, thepending.reject(new Error(\LSP error: ...`))` line — bundle line 376806 above).tool_resulthandler insrc/extensions/lsp.tslogs the wholeErrorobject (console.error("LSP file sync failed:", err)), so Bun renders the error together with its bundled-source code frame.tool_resultcallsgetOrCreateClientagain — re-spawning the doomed server and re-dumping the frame on every file operation.Expected behavior
One human-readable line per session (no code frame), a visible degraded status, and no re-spawn attempts until the next session.