Hmbown/CodeWhale · error

failed to read bounded stdio JSON-RPC frame

Error message

failed to read bounded stdio JSON-RPC frame: {}

What it means

The stdio transport failed while reading a JSON-RPC frame from the child process's stdout under the bounded read (size limit). The frame was invalid (I/O or format error), an error response was sent to the caller, and this error is raised.

Solutions

  1. Inspect the wrapped source error ({err}) to distinguish size-limit vs I/O failure
  2. Check the child's stdout for oversized or non-JSON-RPC output
  3. Verify the configured server command actually speaks newline-delimited JSON-RPC MCP

Example fix

null
Defensive patterns

Strategy: try-catch

Try / catch

match manager.call_tool(...) { Err(e) if e.to_string().starts_with("failed to read bounded stdio JSON-RPC frame") => /* restart child / check stdout */, other => other }

Prevention

When it happens

Trigger: Child process writes a line exceeding the bounded frame size limit; stdout pipe I/O error; child crashes mid-write producing a truncated/partial line; child emits binary garbage instead of newline-delimited JSON-RPC.

Common situations: MCP server binary printing large debug output or huge payloads; wrong binary/path so a non-MCP program writes to stdout; resource limits causing pipe failures.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/4deec07f8b593578. Report an issue: GitHub.

Appendix: source

Thrown at crates/mcp/src/lib.rs:906

    let mut stdout = io::stdout();
    let mut stderr = io::stderr();
    let mut state = build_stdio_state(initial_definitions);
    let mut input = stdin.lock();

    loop {
        let line =
            match stdio_client::read_bounded_line(&mut input, stdio_client::MAX_JSONRPC_LINE_BYTES)
            {
                Ok(Some(line)) => line,
                Ok(None) => break,
                Err(err) => {
                    let response = jsonrpc_error(
                        None,
                        JsonRpcError::parse_error(format!("invalid JSON-RPC frame: {err}")),
                    );
                    writeln!(stdout, "{response}")?;
                    stdout.flush()?;
                    bail!("failed to read bounded stdio JSON-RPC frame: {err}");
                }
            };
        if line.trim().is_empty() {
            continue;
        }

        let value: Value = match serde_json::from_str(&line) {
            Ok(value) => value,
            Err(err) => {
                let msg = jsonrpc_error(
                    None,
                    JsonRpcError::parse_error(format!("invalid json: {err}")),
                );
                writeln!(stdout, "{msg}")?;
                stdout.flush()?;
                continue;
            }
        };

View on GitHub (pinned to 433685b202)