Hmbown/CodeWhale · error
MCP server ' ': timed out after
Error message
MCP server '{}': {} timed out after {:?} What it means
`request` waits on the child's stdout response channel with a hard deadline (`timeout`). If the deadline elapses before a matching response line arrives, the client bails with this timeout error instead of blocking forever on a wedged server. Each request has its own timeout, so this is per-call, not a global connection timeout.
Solutions
- Increase the request timeout for this server if it is legitimately slow (e.g. cold-start installs dependencies).
- Check the server logs (stderr) to see whether the request was received and what it is doing.
- Confirm the server emits responses on stdout as line-delimited JSON-RPC (stdout used for anything else, e.g. debug prints, breaks framing).
- Retry the request; if hangs are recurring, fix or replace the server handler that deadlocks.
Example fix
// before: tight timeout on a slow server let client = spawn_with_timeouts(&config, Duration::from_secs(5), Duration::from_secs(5)).await?; // after: larger request budget let client = spawn_with_timeouts(&config, Duration::from_secs(10), Duration::from_secs(120)).await?;
Defensive patterns
Strategy: try-catch
Try / catch
match conn.request(method, params, timeout).await {
Err(e) if e.to_string().contains("timed out after") => {
eprintln!("{method} exceeded {timeout:?}; increase timeout or investigate the server handler");
// optional: one retry with a longer timeout
}
other => other,
} Prevention
- Set request timeouts from measured server latency plus generous headroom, especially for cold starts.
- Keep server handlers off long-blocking work or make them async/streaming.
- Capture server stderr alongside requests so hangs can be diagnosed after the timeout.
- Alert on per-method timeout rates; a method that always times out is a server bug.
When it happens
Trigger: Calling `request` (from `spawn_with_timeouts` or later use) when the MCP child accepts the stdin write but never sends a JSON-RPC response line on stdout within the allotted `Duration`.
Common situations: The server hangs on the request (deadlocked handler, waiting on network/DB); the request timeout is set too low for a slow server (cold start, first-time tool install); the server responds on stderr but not stdout; a server-side infinite loop on a pathological input.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- MCP server ' ': timed out after
- child returned a malformed MCP CallToolResult
- child stdout was not valid UTF-8
- connection stdin poisoned by an earlier panic
- failed to read bounded stdio JSON-RPC frame
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/606662550a9be4f4.
Report an issue: GitHub.
Appendix: source
Thrown at crates/mcp/src/stdio_client.rs:888
// write loses the race and returns EPIPE. Which one wins is
// platform- and timing-dependent (macOS reliably reports the write
// error where Linux reports the EOF), so both report the death the
// same way rather than leaking a bare "Broken pipe".
if is_broken_pipe(&err) {
bail!(
"MCP server '{server}': process closed stdin before answering {method}{}",
self.exit_note()
);
}
return Err(err)
.with_context(|| format!("MCP server '{server}': failed to send {method}"));
}
let deadline = Instant::now() + timeout;
loop {
let remaining = deadline.saturating_duration_since(Instant::now());
if remaining.is_zero() {
bail!("MCP server '{server}': {method} timed out after {timeout:?}");
}
let line = match self.responses.recv_timeout(remaining) {
Ok(ChildStdoutMessage::Line(line)) => line,
Ok(ChildStdoutMessage::Invalid(error)) => {
bail!(
"MCP server '{server}': invalid child stdout while awaiting {method}: {error}"
);
}
Err(RecvTimeoutError::Timeout) => {
bail!("MCP server '{server}': {method} timed out after {timeout:?}");
}
Err(RecvTimeoutError::Disconnected) => {
bail!(
"MCP server '{server}': process closed stdout before answering {method}{}",
self.exit_note()
);
}
};View on GitHub (pinned to 433685b202)