{"record":{"id":"3c76fe60f58f4ed0","repo":"n8n-io/n8n","slug":"sse-response-has-no-body","errorCode":null,"errorMessage":"SSE response has no body","messagePattern":"SSE response has no body","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/instance-ai/evaluations/clients/sse-client.ts","lineNumber":44,"sourceCode":"\tcookie: string,\n\thandler: (event: SseEvent) => void,\n\tsignal: AbortSignal,\n): Promise<void> {\n\tconst res = await fetch(url, {\n\t\theaders: {\n\t\t\tcookie,\n\t\t\tAccept: 'text/event-stream',\n\t\t},\n\t\tsignal,\n\t});\n\n\tif (!res.ok) {\n\t\tconst text = await res.text();\n\t\tthrow new Error(`SSE connection failed (${res.status}): ${text}`);\n\t}\n\n\tif (!res.body) {\n\t\tthrow new Error('SSE response has no body');\n\t}\n\n\tconst reader = res.body.pipeThrough(new TextDecoderStream()).getReader();\n\n\t// Accumulator for partial lines (SSE data can be split across chunks)\n\tlet buffer = '';\n\n\t// Current event being assembled\n\tlet eventId: string | undefined;\n\tlet eventType: string | undefined;\n\tlet dataLines: string[] = [];\n\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { value, done } = await reader.read();\n\t\t\tif (done) break;\n\n\t\t\tbuffer += value;","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/instance-ai/evaluations/clients/sse-client.ts#L26-L62","documentation":"After the SSE response passes res.ok, the client verifies a readable body exists. A 2xx with no body stream is a contract violation (the runtime/proxy closed the stream early) and the client cannot assemble events, so it fails fast rather than hanging on an empty reader.","triggerScenarios":"A proxy or middleware that returns 200 and swallows the body; a server-side bug closing the stream immediately; a fetch implementation that does not expose streaming bodies.","commonSituations":"Reverse proxies buffering SSE; older runtimes where res.body is undefined for streams; misconfigured compression.","solutions":["Disable response buffering / SSE-unfriendly compression on any proxy in front of n8n.","Run on a runtime that exposes ReadableStream bodies (modern Node/Deno/browsers).","If reproducible, capture the raw response headers to confirm Content-Type:text/event-stream and presence of a body."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Confirm the response advertises a stream:\nconst probe = await fetch(url, { headers: { cookie, Accept: 'text/event-stream' }, signal });\nif (probe.ok && !probe.body) throw new Error('proxy/runtime swallowed SSE body');","typeGuard":"const hasReadableBody = (r: Response): r is Response & { body: ReadableStream } =>\n  Boolean(r.body);","tryCatchPattern":null,"preventionTips":["Disable SSE buffering on proxies in front of n8n.","Use a runtime that exposes ReadableStream bodies.","Set Content-Type:text/event-stream and disable compression for the events route."],"tags":["sse","network","infra"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}