zed-industries/zed · error · anyhow::Error

failed to deserialize response

Error message

failed to deserialize response

What it means

This error occurs in Zed's LSP client when a JSON-RPC response from a language server cannot be deserialized into the expected strongly-typed result of the request (e.g. a `lsp::CompletionResponse` or `lsp::Hover`). The client wraps the serde/serde_json error with the context string "failed to deserialize response", and the future returned by `LanguageServer::request` resolves to this error. It indicates the server replied, but the payload shape did not match the LSP schema Zed expected — usually a server that emits non-conformant JSON, or a Zed-side type mismatch between the lsp-types version and what the server sends.

Source

Thrown at crates/lsp/src/lsp.rs:1552

            .lock()
            .as_mut()
            .context("server shut down")
            .map(|handlers| {
                let executor = executor.clone();
                handlers.insert(
                    RequestId::Int(id),
                    Box::new(move |result| {
                        executor
                            .spawn(async move {
                                let response = match result {
                                    Ok(response) => match deserialize_result(&response) {
                                        Ok(deserialized) => Ok(deserialized),
                                        Err(error) => {
                                            log::error!("failed to deserialize response from language server: {}. response from language server: {:?}", error, response);
                                            Err(error).context("failed to deserialize response")
                                        }
                                    }
                                    Err(error) => Err(anyhow::Error::new(error)),
                                };
                                tx.send(response).ok();
                            })
                    }),
                );
            });

        let send = outbound_tx
            .try_send(message)
            .context("failed to write to language server's stdin");

        let response_handlers = Arc::clone(response_handlers);
        let notification_serializers = notification_serializers.downgrade();
        let started = Instant::now();
        LspRequest::new(id, async move {
            if let Err(e) = handle_response {
                return ConnectionResult::Result(Err(e));
            }

View on GitHub (pinned to 9d272b0363)

Solutions

  1. Check the Zed log (the `log::error!` at crates/lsp/src/lsp.rs:1545 includes the raw server response) to see the exact serde error and offending payload.
  2. Update the language server binary to a released version; non-conformant responses are often fixed upstream.
  3. Update Zed (or lsp-types/zed's LSP adapter) so its expected response types match the server's LSP dialect.
  4. If a specific server is at fault, file/lookup an issue on the server; as a workaround, disable or downgrade that extension/server version.
  5. If you develop the adapter (languages/src/*_language_server), normalize the server's quirks in the adapter before the response reaches the typed request path.
Defensive patterns

Strategy: try-catch

Validate before calling

// No pre-call validation is possible: the payload shape is decided by the server.
// Log the raw response at the adapter layer to make failures debuggable:
tracing::debug!(response = %raw_response_json, "server response for {}", T::METHOD);

Type guard

fn is_deserialize_failure(err: &anyhow::Error) -> bool {
    err.chain().any(|c| c.to_string().contains("failed to deserialize response"))
}

Try / catch

match server.request::<lsp::request::Completion>(&params).await {
    Ok(result) => result,
    Err(err) if is_deserialize_failure(&err) => {
        log::warn!("server sent non-conformant response: {err:#}");
        Default::default() // fall back to empty completion result
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: Calling `LanguageServer::request::<T>()` (crates/lsp/src/lsp.rs `request_internal_with_timer`, line 1542 `deserialize_result`) where the server's response body fails `serde_json` deserialization into `T::Result` — e.g. a server returning `null` result for a non-nullable request type, a completion item with wrong-typed fields, unknown enum variant, or missing required fields.

Common situations: Using a language server version that emits LSP 3.17+ fields Zed's pinned lsp-types version rejects or a server with known spec violations (e.g. some Rust Analyzer/clangd/gopls edge responses, jdtls returning null results for textDocument/documentSymbol); server extensions that add fields with wrong types; running a dev build of a language server against a newer Zed or vice versa.

Related errors


AI-assisted analysis of zed-industries/zed@9d272b0363 (2026-09-05). Data as JSON: /api/errors/190dcc441fc8e3db. Report an issue: GitHub.