{"record":{"id":"d8dbf95718d19c3f","repo":"Hmbown/CodeWhale","slug":"message","errorCode":null,"errorMessage":"{message}","messagePattern":"\\{message\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/lsp/client.rs","lineNumber":325,"sourceCode":"        let payload = json!({\n            \"jsonrpc\": \"2.0\",\n            \"id\": id,\n            \"method\": method,\n            \"params\": params,\n        });\n        if let Err(err) = send_message(&self.tx_outbound, &payload).await {\n            let mut pending = self.pending.lock().await;\n            pending.remove(&id);\n            return Err(err);\n        }\n        match timeout(wait, rx).await {\n            Ok(Ok(reply)) => {\n                if let Some(error) = reply.get(\"error\") {\n                    let message = error\n                        .get(\"message\")\n                        .and_then(|v| v.as_str())\n                        .unwrap_or(\"LSP request failed\");\n                    return Err(anyhow!(\"{message}\"));\n                }\n                Ok(reply.get(\"result\").cloned().unwrap_or(Value::Null))\n            }\n            Ok(Err(_)) => Err(anyhow!(\"LSP request channel closed\")),\n            Err(_) => {\n                let mut pending = self.pending.lock().await;\n                pending.remove(&id);\n                Err(anyhow!(\"LSP request timed out for {method}\"))\n            }\n        }\n    }\n\n    async fn shutdown(&self) {\n        let mut child = self.child.lock().await;\n        if let Some(mut c) = child.take() {\n            let _ = c.start_kill();\n            let _ = c.wait().await;\n        }","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/lsp/client.rs#L307-L343","documentation":"The LSP client received a JSON-RPC reply carrying an error object and converts it into an error using the server's message field (falling back to 'LSP request failed' when the field is missing or not a string). The text is whatever the language server chose: unsupported method, invalid params, or a server-internal failure. This is a protocol-level error delivered per request, not a transport failure.","triggerScenarios":"Requests such as textDocument/hover, definition, or rename against a server that does not advertise or implement the method; params referencing a document the server has not seen (no didOpen); stale document versions after rapid edits; requests issued before initialization completes.","commonSituations":"Calling optional methods on minimal servers, skipping didOpen so the server rejects unknown files, version drift between editor and server buffers, older server builds with different capability surfaces.","solutions":["Read the message text; it names the server-side cause (method not found, invalid params, internal error)","Gate optional calls on the capabilities the server returned in its initialize result","Ensure documents are opened and synced (didOpen/didChange) before querying them","Update or restart the language server if it reports internal errors"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Only call optional methods the server advertised in its initialize result\nfn supports(server_caps: &serde_json::Value, method: &str) -> bool {\n    let on = |ptr: &str| server_caps.pointer(ptr).and_then(|v| v.as_bool()).unwrap_or(false);\n    match method {\n        \"textDocument/hover\" => on(\"/capabilities/hoverProvider\"),\n        \"textDocument/rename\" => on(\"/capabilities/renameProvider\"),\n        \"textDocument/formatting\" => on(\"/capabilities/documentFormattingProvider\"),\n        _ => true,\n    }\n}","typeGuard":null,"tryCatchPattern":"// anyhow carries the server's message; branch on its content\nif let Err(err) = client.request(\"textDocument/hover\", params).await {\n    let msg = err.to_string();\n    if msg.contains(\"not supported\") || msg.contains(\"Unhandled method\") || msg.contains(\"unknown method\") {\n        // capability gap: degrade gracefully\n    } else {\n        return Err(err);\n    }\n}","preventionTips":["Gate optional requests on advertised capabilities","Complete the initialize handshake before any other request","Keep didOpen/didChange in sync before querying documents","Capture server logs beside client logs to correlate JSON-RPC error codes"],"tags":["lsp","jsonrpc","protocol","client"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}