{"record":{"id":"517bf7296f9c6087","repo":"Kuberwastaken/claurst","slug":"mcp-server-failed-to-read-legacy-sse-http-re","errorCode":null,"errorMessage":"MCP server '{}': failed to read legacy SSE HTTP response body: {}","messagePattern":"MCP server '(.+?)': failed to read legacy SSE HTTP response body: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-rust/crates/mcp/src/rmcp_backend.rs","lineNumber":478,"sourceCode":"            if let Err(e) = transport::process_sse_response(response, |_, data| {\n                if data.trim().is_empty() {\n                    return Ok(());\n                }\n                let message = parse_server_message(&server_name_for_task, data)?;\n                let _ = incoming_tx.send(message);\n                Ok(())\n            })\n            .await\n            {\n                tracing::warn!(server = %server_name_for_task, error = %e, \"legacy SSE POST stream closed with error\");\n            }\n        });\n        lock_recover(&background_tasks).push(task);\n        return Ok(());\n    }\n\n    let text = response.text().await.map_err(|e| {\n        anyhow::anyhow!(\n            \"MCP server '{}': failed to read legacy SSE HTTP response body: {}\",\n            server_name,\n            e\n        )\n    })?;\n    if text.trim().is_empty() {\n        return Ok(());\n    }\n\n    let message = parse_server_message(&server_name, &text)?;\n    let _ = incoming_tx.send(message);\n    Ok(())\n}\n\n#[async_trait]\nimpl McpClientBackend for RmcpClientBackend {\n    fn kind(&self) -> McpBackendKind {\n        McpBackendKind::Rmcp","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/mcp/src/rmcp_backend.rs#L460-L496","documentation":"Raised in `handle_legacy_sse_http_response` when the POST to a legacy SSE MCP server succeeded at the HTTP-status level (success or 202) and the response is not an event-stream, but `response.text().await` fails while reading the plain JSON body. This means the connection broke or the body could not be buffered before a complete response was received. The server name and the reqwest error are wrapped so the failing MCP server can be identified.","triggerScenarios":"Calling any MCP operation whose POST response is a plain JSON body (not SSE, not 202) and the HTTP connection drops while the body is being read: server closes the socket early, network interruption, proxy terminating the connection, or response body larger than allowed and the connection aborted.","commonSituations":"An intermediary (nginx/Envoy) timing out the request and cutting the connection; server crashing mid-response; flaky network to a remote MCP host; keep-alive race where the server closed an idle connection just as the client reused it.","solutions":["Retry the MCP operation — this is often a transient connection drop.","Check proxy/load-balancer timeouts between client and MCP server and raise them.","Check MCP server logs for a crash or premature exit during request handling.","If it recurs, switch the MCP server config to the streamable-HTTP transport, which handles connection churn better."],"exampleFix":"// before: single-shot call that surfaces the read failure to the user\nlet tools = backend.list_tools().await?;\n// after: bounded retry for transient body-read failures\nlet tools = match backend.list_tools().await {\n    Ok(t) => t,\n    Err(e) if e.to_string().contains(\"failed to read legacy SSE HTTP response body\") => {\n        tokio::time::sleep(Duration::from_millis(250)).await;\n        backend.list_tools().await?\n    }\n    Err(e) => return Err(e),\n};","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match backend.call_tool(name, args).await {\n    Ok(r) => r,\n    Err(e) if e.to_string().contains(\"failed to read legacy SSE HTTP response body\") => {\n        tokio::time::sleep(Duration::from_millis(250)).await;\n        backend.call_tool(name, args).await?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Raise proxy/load-balancer read timeouts for long-running MCP tool calls.","Prefer the streamable-HTTP transport when the server supports it; plain SSE POST bodies are more fragile.","Retry transient body-read failures with backoff — they are usually not deterministic.","Monitor MCP server stability; a server that drops connections mid-response will also drop SSE streams."],"tags":["network","mcp","sse","http-body","transient"],"backgroundTag":"http-request-failed","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}