Hmbown/CodeWhale · error

failed to read bounded stdio JSON-RPC frame

Error message

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

What it means

The stdio JSON-RPC transport reads length/size-bounded frames (lines) from the child process. When reading a frame fails (IO error, oversized/bounded-frame violation), the transport emits a JSON-RPC parse error response and then bails with this message naming the underlying error. It signals the stdio channel with the MCP child is broken or misbehaving.

Solutions

  1. Check the child process is alive and healthy (exit status, stderr logs); restart the MCP server process and retry.
  2. Reduce frame size (limit tool output / request size) or raise the configured read bound if it is genuinely too small.
  3. Inspect the embedded {err} for the root cause: pipe closed vs size limit vs IO error, and fix accordingly (fix child crash, adjust limit, check permissions).
Defensive patterns

Strategy: retry

Validate before calling

fn child_alive(child: &std::process::Child) -> bool {
    matches!(child.try_wait(), Ok(None))
}
// verify child liveness (and that a frame size limit is configured generously) before issuing requests

Try / catch

match transport.call(request) {
    Err(e) if e.to_string().contains("failed to read bounded stdio JSON-RPC frame") => {
        tracing::error!("stdio transport failed: {e}; restarting server");
        restart_child()?; // then retry once
    }
    other => other,
}

Prevention

When it happens

Trigger: A read of a bounded stdio JSON-RPC frame from the child process returns an error (err), e.g. the frame exceeds the size bound, the pipe closed mid-frame, or an OS-level read failure.

Common situations: Child process crashed or exited while a request was in flight; child emitted a frame larger than the configured bound (huge tool output); broken pipe after the child was killed by OOM or signal; non-JSON-RPC output corrupting the framing.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/c72141e0177367e3. 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 73e0f67d83)