{"record":{"id":"d09585e2cd2be006","repo":"Hmbown/CodeWhale","slug":"mcp-response-content-length-len-exceeds-bytes","errorCode":null,"errorMessage":"MCP response Content-Length {len} exceeds {} bytes — aborting","messagePattern":"MCP response Content-Length (.+?) exceeds (.+?) bytes — aborting","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp/streamable_http.rs","lineNumber":124,"sourceCode":"                mask_url_secrets(&self.url),\n                status,\n                body_excerpt,\n            )));\n        }\n\n        let content_type = response\n            .headers()\n            .get(CONTENT_TYPE)\n            .and_then(|value| value.to_str().ok())\n            .map(str::to_string);\n        // Reject an over-large declared body before reading anything (fast\n        // path), then bound the read itself so chunked / length-less\n        // responses cannot OOM us either — Content-Length alone does not\n        // protect against a server that streams without declaring a length.\n        if let Some(len) = response.content_length()\n            && len > MAX_MCP_RESPONSE_BYTES as u64\n        {\n            return Err(StreamableSendError::Other(anyhow::anyhow!(\n                \"MCP response Content-Length {len} exceeds {} bytes — aborting\",\n                MAX_MCP_RESPONSE_BYTES\n            )));\n        }\n        let body = read_body_capped(response, MAX_MCP_RESPONSE_BYTES)\n            .await\n            .map_err(StreamableSendError::Other)?;\n        self.store_response_body(content_type.as_deref(), &body)\n            .map_err(StreamableSendError::Other)\n    }\n\n    pub(super) async fn recv(&mut self) -> Result<Vec<u8>> {\n        self.pending_messages\n            .pop_front()\n            .context(\"MCP Streamable HTTP response queue is empty\")\n    }\n\n    fn store_response_body(&mut self, content_type: Option<&str>, body: &str) -> Result<()> {","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/mcp/streamable_http.rs#L106-L142","documentation":"Fast-path guard: the HTTP response declares a Content-Length larger than MAX_MCP_RESPONSE_BYTES (16 MiB, crates/tui/src/mcp/wire.rs), so the body is rejected before any byte is read. This stops a misbehaving or malicious server from OOM-ing the client at transport-read time with an oversized response.","triggerScenarios":"A tool result or resource read returns a declared body over 16 MiB — e.g. a filesystem or grep MCP tool inlining an entire large file in one response.","commonSituations":"Tools without pagination reading big files or logs; servers embedding large base64 blobs; hostile servers probing client limits.","solutions":["Shrink the server response: paginate tool results, cap file reads, return references instead of inlining content","Narrow the tool arguments (offset/limit, path filters, query terms) so each response stays under 16 MiB","Split the work into multiple smaller tool calls when neither side is under your control"],"exampleFix":"// before: server inlines the whole file in one result\ncontent = fs.read_text(path).await?;\n\n// after: page the content\ncontent = fs.read_text_range(path, offset, limit).await?;","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"On this deterministic cap rejection, fall back to a narrower request rather than repeating the call:\n```rust\nmatch tool_call(&args).await {\n    Err(e) if e.to_string().contains(\"Content-Length\") && e.to_string().contains(\"exceeds\") => {\n        tool_call(&args.with_page(next_page())).await // paginate\n    }\n    other => other?,\n}\n```","preventionTips":["Design MCP tools to paginate large outputs by default","Return references or URIs for large content instead of inlining it in tool results"],"tags":["mcp","http","limits","response-size"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}