{"record":{"id":"8fc5de8b86bd88f3","repo":"Hmbown/CodeWhale","slug":"lsp-semantic-request-timed-out-sending-document","errorCode":null,"errorMessage":"LSP semantic request timed out sending document","messagePattern":"LSP semantic request timed out sending document","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/lsp/client.rs","lineNumber":444,"sourceCode":"\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        let deadline = tokio::time::Instant::now() + wait;\n        let _gate = timeout(wait, self.diagnostics_gate.lock())\n            .await\n            .map_err(|_| anyhow!(\"LSP semantic request timed out waiting for another document\"))?;\n        let (_, version) = timeout(\n            deadline.saturating_duration_since(tokio::time::Instant::now()),\n            self.open_or_change(path, text),\n        )\n        .await\n        .map_err(|_| anyhow!(\"LSP semantic request timed out sending document\"))??;\n        let result = self\n            .request(\n                method,\n                params,\n                deadline.saturating_duration_since(tokio::time::Instant::now()),\n            )\n            .await?;\n        Ok(SemanticReply {\n            result,\n            document_version: Some(version),\n        })\n    }\n\n    async fn ensure_open(&self, path: &Path, text: &str) -> Result<()> {\n        let _gate = self.diagnostics_gate.lock().await;\n        self.open_or_change(path, text).await?;\n        Ok(())\n    }","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/lsp/client.rs#L426-L462","documentation":"After acquiring the gate, request_for_document sends the document via open_or_change under the remaining deadline. This error means the send did not finish before the deadline — the document update itself is stuck (backpressure, dead server, or full queue), so the subsequent LSP method request would operate on stale text and is skipped.","triggerScenarios":"open_or_change blocked behind a full outbound channel while the server is unresponsive; deadline nearly exhausted after a long gate wait so almost no time remains for the send; language-server process hung.","commonSituations":"Server wedged mid-session so writes never drain; semantic request issued at the tail of a tight deadline after contending on the gate; test harness with very short waits against a slow fake server.","solutions":["Increase the wait budget, ensuring the send phase has meaningful time left after gate acquisition","Check the language-server process health and restart it if the outbound queue is not draining","Reduce concurrent document churn so the outbound channel is not backlogged","Retry with a fresh deadline"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// reserve send time: don't call when the deadline is nearly spent\nlet remaining = deadline.saturating_duration_since(Instant::now());\nif remaining < Duration::from_millis(500) { bail!(\"not enough budget left to send document\"); }","typeGuard":null,"tryCatchPattern":"match client.request_for_document(path, text, method, params, wait).await {\n    Ok(reply) => reply,\n    Err(e) if e.to_string().contains(\"timed out sending document\") => {\n        check_server_alive(&client).await?;\n        client.request_for_document(path, text, method, params, wait).await\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Give the total wait enough headroom after gate acquisition for the send plus reply","Watch outbound queue depth; a wedged server never drains didChange","Restart the language server when sends start timing out repeatedly","Avoid flooding didChange for many documents at once"],"tags":["lsp","timeout","backpressure"],"backgroundTag":"request-timeout","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}