Hmbown/CodeWhale · error · io::Error
MCP stdio line exceeded
Error message
MCP stdio line exceeded {max} bytes What it means
read_line_capped enforces a per-line byte cap on the MCP stdio transport. As it accumulates bytes it errors with InvalidData once the buffered line exceeds max, preventing a misbehaving or malicious server from exhausting memory with an unterminated line.
Solutions
- Fix or update the MCP server so it emits frames within the size cap.
- Raise the transport's max line size if your server legitimately sends very large responses.
- Inspect server stderr/logs for corrupted output causing unbounded lines.
Defensive patterns
Strategy: retry
Try / catch
match recv().await {
Err(e) if e.to_string().contains("line exceeded") => {
eprintln!("server sent an oversized frame; restart server or raise max");
restart_server_and_retry().await
}
other => other,
} Prevention
- Keep MCP server responses within the transport's line cap; paginate large results.
- Configure a max line size comfortably above your server's largest legitimate frame.
- Treat unbounded output from a server as a server bug to fix.
When it happens
Trigger: recv (or the tests cancelled_partial_read_preserves_next_frame / aborts_on_newline_free_line_over_cap) reads a line from the MCP stdio server whose length surpasses the configured max before a newline arrives.
Common situations: A server emitting huge JSON-RPC frames on a single line; a broken server writing binary/noise without newlines; a misconfigured max line size that is smaller than legitimate responses.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- JSON-RPC line exceeded the
- child returned a malformed MCP CallToolResult
- child stdout was not valid UTF-8
- connection stdin poisoned by an earlier panic
- exceeded the -item catalogue limit
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/31a37bebcd4ff6db.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp/stdio.rs:434
{
use tokio::io::AsyncBufReadExt;
loop {
let (chunk, consumed, done) = {
let available = reader.fill_buf().await?;
if available.is_empty() {
(Vec::new(), 0usize, true)
} else if let Some(pos) = available.iter().position(|&b| b == b'\n') {
(available[..=pos].to_vec(), pos + 1, true)
} else {
(available.to_vec(), available.len(), false)
}
};
if consumed > 0 {
reader.consume(consumed);
}
out.extend_from_slice(&chunk);
if out.len() > max {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("MCP stdio line exceeded {max} bytes"),
));
}
if done {
break;
}
}
Ok(out.len())
}
#[cfg(test)]
mod read_cap_tests {
use super::read_line_capped;
#[tokio::test]
async fn cancelled_partial_read_preserves_next_frame() {
use futures_util::FutureExt;View on GitHub (pinned to 73e0f67d83)