BoundaryML/baml · error · LspError

Failed to serialize request result: {0}

Error message

Failed to serialize request result: {0}

What it means

LspError::RequestSerializeError occurs when the server cannot serialize a request's result value to JSON (serde_json::Error) before sending it back over the wire. thiserror formats it as 'Failed to serialize request result: {0}'.

Source

Thrown at baml_language/crates/baml_lsp/src/error.rs:19

//! The one LSP error type and its JSON-RPC code table.

use std::path::PathBuf;

/// Every failure a request or notification handler can report.
///
/// Serialized to the wire exclusively through [`LspError::to_response_error`];
/// the legacy `-32001 UnknownErrorCode` is never emitted.
#[derive(Debug, thiserror::Error)]
pub enum LspError {
    #[error("{0}")]
    NotificationExtractError(lsp_server::ExtractError<lsp_server::Notification>),
    #[error("Notification not supported: {0}")]
    NotificationNotSupported(String),
    #[error("{0}")]
    RequestExtractError(lsp_server::ExtractError<lsp_server::Request>),
    #[error("Request not supported: {0}")]
    RequestNotSupported(String),
    #[error("Failed to serialize request result: {0}")]
    RequestSerializeError(serde_json::Error),
    /// The client's sink is gone; nothing more can be delivered.
    #[error("Client closed")]
    ClientClosed,
    /// Bounded transport backpressure (LSP `RequestFailed`, `-32803`).
    #[error("LSP outbound sink is saturated")]
    OutboundSaturated,
    /// A frame larger than the transport limit (LSP `RequestFailed`,
    /// `-32803`).
    #[error("LSP outbound frame exceeds the transport limit")]
    OutboundOversized,
    #[error("Invalid command arguments for command: {command}: {message}")]
    InvalidCommandArguments { command: String, message: String },
    #[error("File not found: {}", .0.display())]
    FileNotFound(PathBuf),
    #[error("Path is invalid: {}: {message}", path.display())]
    InvalidPath { path: PathBuf, message: String },
    /// The document's path is under no known source root.

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Read the inner serde_json error to find the unserializable field
  2. Ensure all response types (and nested types) derive or implement serde::Serialize
  3. Sanitize f64 values (replace NaN/Infinity) before returning them as results

Example fix

// before
#[derive(Debug)]
struct HoverData { value: f64 }
// after
#[derive(serde::Serialize)]
struct HoverData { #[serde(skip_serializing_if = "f64::is_nan")] value: f64 }
Defensive patterns

Strategy: validation

Validate before calling

let json = serde_json::to_value(&result).map_err(|e| LspError::RequestSerializeError(e))?;

Try / catch

match build_response() {
    Err(LspError::RequestSerializeError(e)) => log::error!("unserializable result: {e}"),
    other => other?,
}

Prevention

When it happens

Trigger: A handler returns a result value whose serde Serialize impl fails — e.g. NaN/f64 in a JSON position, non-string map keys, or a type missing Serialize derives — inside a response-building path.

Common situations: Adding a new LSP request handler and forgetting #[derive(Serialize)] on a nested type; returning f64::NAN from a hover position; serializing maps with non-string keys.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/b16b024050bbe2b1. Report an issue: GitHub.