Hmbown/CodeWhale · error
LSP response has no result
Error message
LSP response has no result
What it means
The JSON-RPC response contained neither an `error` nor a `result` field. A valid JSON-RPC reply must carry one of the two, so the library treats a bare response as a malformed reply and errors rather than returning null to the caller.
Solutions
- Fix the server/stub to include a `result` field (JSON null is acceptable) in every response
- Log the raw reply frame to confirm what the server actually sent
- Check for framing/parsing bugs between the server and this client that could truncate the payload
- If the server legitimately returns null, encode it as `{"result": null}` not an absent field
Example fix
// before (stub reply)
json!({"id": 1, "jsonrpc": "2.0"})
// after
json!({"id": 1, "jsonrpc": "2.0", "result": null}) Defensive patterns
Strategy: validation
Validate before calling
// validate the stub/server reply shape before treating it as a response
fn is_valid_jsonrpc_reply(reply: &Value) -> bool {
reply.get("result").is_some() || reply.get("error").is_some()
} Type guard
fn has_result(reply: &serde_json::Value) -> Option<&serde_json::Value> {
if reply.get("error").is_none() && reply.get("result").is_some() {
reply.get("result")
} else {
None
}
} Try / catch
match client.request(method, params, wait).await {
Ok(reply) => reply,
Err(e) if e.to_string() == "LSP response has no result" => {
// malformed server reply: log raw frame, fall back to empty result
log_raw_frame(method);
Ok(Value::Null)
}
Err(e) => return Err(e),
} Prevention
- Ensure test stubs always include a `result` (null counts) or `error` field
- Conform to JSON-RPC 2.0 framing in any custom server
- Log raw inbound frames to catch truncation/misparsing upstream
- Avoid middleware that can strip response fields
When it happens
Trigger: A non-conformant server sends a response missing both fields; a reply frame got corrupted or mis-parsed upstream so only metadata survived; forwarding proxies/middleware stripped the result.
Common situations: Custom or in-development language servers with incomplete JSON-RPC framing; tests using hand-rolled stub replies; intermediate serialization layers dropping null-ish results incorrectly.
Related errors
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/41a72425a0fd46de.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/lsp/client.rs:501
let response = timeout(wait, async {
send_message(&self.tx_outbound, &payload).await?;
rx.await.map_err(|_| anyhow!("LSP request channel closed"))
})
.await;
self.pending.lock().await.remove(&id);
match response {
Ok(Ok(reply)) => {
if let Some(error) = reply.get("error") {
let message = error
.get("message")
.and_then(Value::as_str)
.unwrap_or("LSP request failed");
return Err(anyhow!("{message}"));
}
reply
.get("result")
.cloned()
.ok_or_else(|| anyhow!("LSP response has no result"))
}
Ok(Err(error)) => Err(error),
Err(_) => Err(anyhow!("LSP request timed out for {method}")),
}
}
async fn shutdown(&self) {
let mut child = self.child.lock().await;
if let Some(mut c) = child.take() {
let _ = c.start_kill();
let _ = c.wait().await;
}
for task in &self.tasks {
task.abort();
}
self.pending.lock().await.clear();
}
}View on GitHub (pinned to 73e0f67d83)