{"record":{"id":"3e2a0253418b68df","repo":"Hmbown/CodeWhale","slug":"lsp-semantic-request-timed-out","errorCode":null,"errorMessage":"LSP semantic request timed out","messagePattern":"LSP semantic request timed out","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/lsp/client.rs","lineNumber":130,"sourceCode":"    /// Synchronize and query one document atomically when the transport can\n    /// prove that ordering. Diagnostic-only/legacy transports stay unverified.\n    async fn request_for_document(\n        &self,\n        path: &Path,\n        text: &str,\n        method: &str,\n        params: Value,\n        wait: Duration,\n    ) -> Result<SemanticReply> {\n        timeout(wait, async {\n            self.ensure_open(path, text).await?;\n            Ok(SemanticReply {\n                result: self.request(method, params, wait).await?,\n                document_version: None,\n            })\n        })\n        .await\n        .map_err(|_| anyhow!(\"LSP semantic request timed out\"))?\n    }\n\n    /// Ensure `path` is open with `text` (didOpen/didChange) so position-based\n    /// requests can target it. Default is a no-op; real transports track opens.\n    async fn ensure_open(&self, _path: &Path, _text: &str) -> Result<()> {\n        Ok(())\n    }\n\n    /// A closed transport is never valid cache evidence. Diagnostic-only\n    /// in-process implementations remain usable until their owner removes them.\n    fn is_alive(&self) -> bool {\n        true\n    }\n\n    /// Best-effort shutdown. Called via `LspManager::shutdown_all`.\n    async fn shutdown(&self);\n}\n","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/lsp/client.rs#L112-L148","documentation":"`request_for_document` wraps the semantic request in `tokio::time::timeout`; this error fires when the inner request does not complete within the allotted wait. The reply never arrived in time, so the semantic operation is abandoned.","triggerScenarios":"LSP server slow or hung answering the request; wait duration too short for large documents or slow servers; transport deadlock so no response is ever produced.","commonSituations":"Large monorepo files where rust-analyzer/clangd takes seconds to index; server crashed mid-request; wait configured to a few hundred milliseconds.","solutions":["Increase the wait duration passed to the request","Check the LSP server is still alive and producing logs","Retry the request once on timeout before failing the user action","Verify the request id/response matching works (no dropped responses)"],"exampleFix":"// before\nlet wait = Duration::from_millis(500);\nlet reply = request_for_document(transport, path, method, params, wait).await?;\n// after\nlet wait = Duration::from_secs(10); // semantic replies can be slow\nlet reply = request_for_document(transport, path, method, params, wait).await;","handlingStrategy":"retry","validationCode":"// before issuing: ensure server responsive\nlet ping = tokio::time::timeout(Duration::from_secs(2), transport.request(\"shutdown\", json!({}), Duration::from_secs(1))).await.is_ok();","typeGuard":null,"tryCatchPattern":"match request_for_document(...).await {\n    Err(e) if e.to_string().contains(\"timed out\") => request_for_document(... with 3x wait).await,\n    other => other,\n}","preventionTips":["Size the wait to the slowest expected server (seconds, not ms)","Pre-warm the server before user-triggered semantic requests","Log server stderr to catch hangs early"],"tags":["lsp","timeout","async"],"backgroundTag":"request-timeout","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T06:17:15.046Z"}