{"record":{"id":"606662550a9be4f4","repo":"Hmbown/CodeWhale","slug":"mcp-server-timed-out-after","errorCode":null,"errorMessage":"MCP server '{}': {} timed out after {:?}","messagePattern":"MCP server '(.+?)': (.+?) timed out after (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mcp/src/stdio_client.rs","lineNumber":888,"sourceCode":"            // write loses the race and returns EPIPE. Which one wins is\n            // platform- and timing-dependent (macOS reliably reports the write\n            // error where Linux reports the EOF), so both report the death the\n            // same way rather than leaking a bare \"Broken pipe\".\n            if is_broken_pipe(&err) {\n                bail!(\n                    \"MCP server '{server}': process closed stdin before answering {method}{}\",\n                    self.exit_note()\n                );\n            }\n            return Err(err)\n                .with_context(|| format!(\"MCP server '{server}': failed to send {method}\"));\n        }\n\n        let deadline = Instant::now() + timeout;\n        loop {\n            let remaining = deadline.saturating_duration_since(Instant::now());\n            if remaining.is_zero() {\n                bail!(\"MCP server '{server}': {method} timed out after {timeout:?}\");\n            }\n            let line = match self.responses.recv_timeout(remaining) {\n                Ok(ChildStdoutMessage::Line(line)) => line,\n                Ok(ChildStdoutMessage::Invalid(error)) => {\n                    bail!(\n                        \"MCP server '{server}': invalid child stdout while awaiting {method}: {error}\"\n                    );\n                }\n                Err(RecvTimeoutError::Timeout) => {\n                    bail!(\"MCP server '{server}': {method} timed out after {timeout:?}\");\n                }\n                Err(RecvTimeoutError::Disconnected) => {\n                    bail!(\n                        \"MCP server '{server}': process closed stdout before answering {method}{}\",\n                        self.exit_note()\n                    );\n                }\n            };","sourceCodeStart":870,"sourceCodeEnd":906,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/mcp/src/stdio_client.rs#L870-L906","documentation":"`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.","triggerScenarios":"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`.","commonSituations":"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.","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."],"exampleFix":"// before: tight timeout on a slow server\nlet client = spawn_with_timeouts(&config, Duration::from_secs(5), Duration::from_secs(5)).await?;\n// after: larger request budget\nlet client = spawn_with_timeouts(&config, Duration::from_secs(10), Duration::from_secs(120)).await?;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match conn.request(method, params, timeout).await {\n    Err(e) if e.to_string().contains(\"timed out after\") => {\n        eprintln!(\"{method} exceeded {timeout:?}; increase timeout or investigate the server handler\");\n        // optional: one retry with a longer timeout\n    }\n    other => other,\n}","preventionTips":["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."],"tags":["mcp","timeout","stdio","hang"],"backgroundTag":"request-timeout","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}