{"record":{"id":"27d3f00ccc350dfc","repo":"Hmbown/CodeWhale","slug":"sse-buffer-exceeded-max-sse-buf-bytes-aborting","errorCode":null,"errorMessage":"SSE buffer exceeded {MAX_SSE_BUF} bytes — aborting stream","messagePattern":"SSE buffer exceeded (.+?) bytes — aborting stream","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/client/chat.rs","lineNumber":1344,"sourceCode":"                             (elapsed: {}ms, bytes_received: {}, ms_since_last_event: {}, headers: {})\",\n                            stream_start.elapsed().as_millis(),\n                            bytes_received,\n                            last_event_at.elapsed().as_millis(),\n                            response_headers,\n                        ));\n                        yield Err(anyhow::anyhow!(\"Stream read error: {e}\"));\n                        break;\n                    }\n                };\n\n                bytes_received = bytes_received.saturating_add(chunk.len());\n                last_event_at = std::time::Instant::now();\n                byte_buf.extend_from_slice(&chunk);\n\n                // Guard against unbounded buffer growth (e.g., malformed stream without newlines)\n                const MAX_SSE_BUF: usize = 10 * 1024 * 1024; // 10 MB\n                if byte_buf.len() > MAX_SSE_BUF {\n                    yield Err(anyhow::anyhow!(\"SSE buffer exceeded {MAX_SSE_BUF} bytes — aborting stream\"));\n                    break;\n                }\n\n                if byte_buf.len() > SSE_BACKPRESSURE_HIGH_WATERMARK {\n                    tokio::time::sleep(Duration::from_millis(SSE_BACKPRESSURE_SLEEP_MS)).await;\n                }\n\n                // Process complete SSE lines from the buffer. Strict UTF-8:\n                // never `from_utf8_lossy` here — a mid-character TCP split\n                // stays in `byte_buf` until `\\n`, and a genuinely invalid\n                // line fails closed instead of injecting U+FFFD (#5374).\n                let mut lines_processed = 0usize;\n                loop {\n                    let line = match super::take_sse_line(&mut byte_buf) {\n                        Ok(Some(line)) => line,\n                        Ok(None) => break,\n                        Err(err) => {\n                            yield Err(anyhow::anyhow!(\"{err}\"));","sourceCodeStart":1326,"sourceCodeEnd":1362,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/client/chat.rs#L1326-L1362","documentation":"Guard against unbounded buffer growth: the raw SSE byte buffer grew past 10 MB without yielding a complete line, so the client aborts the stream. A legitimate SSE response virtually never has 10 MB with no newline; this indicates a malformed stream — data arriving with no line delimiters at all.","triggerScenarios":"Server sends one giant unbroken line (no `\\n`); a misbehaving proxy strips newlines; a non-SSE body (binary, JSON blob, HTML error page) is served on the streaming endpoint.","commonSituations":"Wrong base URL where the endpoint returns a plain JSON body instead of SSE; upstream bug emitting an unterminated payload; intermediary response rewriting.","solutions":["Verify the endpoint actually returns an SSE stream (correct URL and `stream: true` request shape)","Retry once — an occasional malformed response is transient","Capture the buffered bytes to identify what is actually being sent","If deterministic, the endpoint/URL is wrong or the upstream is broken — report or fix the route"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_sse_buffer_overflow(err: &anyhow::Error) -> bool {\n    err.to_string().starts_with(\"SSE buffer exceeded\")\n}","tryCatchPattern":"match stream.next().await {\n    Some(Err(e)) if is_sse_buffer_overflow(&e) => {\n        // 10MB with no newline = not an SSE stream; do not retry the same URL blindly\n        return Err(e.context(\"endpoint is not returning newline-delimited SSE\"));\n    }\n    other => { /* forward */ }\n}","preventionTips":["Verify the endpoint and request shape actually produce SSE before streaming","Do not disable or raise the buffer guard — it exists to stop malformed streams","Test new base URLs with a tiny request first to confirm line-delimited output"],"tags":["sse","memory","guard","malformed-stream"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}