n8n-io/n8n · error · Error

SSE response has no body

Error message

SSE response has no body

What it means

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.

Source

Thrown at packages/@n8n/instance-ai/evaluations/clients/sse-client.ts:44

	cookie: string,
	handler: (event: SseEvent) => void,
	signal: AbortSignal,
): Promise<void> {
	const res = await fetch(url, {
		headers: {
			cookie,
			Accept: 'text/event-stream',
		},
		signal,
	});

	if (!res.ok) {
		const text = await res.text();
		throw new Error(`SSE connection failed (${res.status}): ${text}`);
	}

	if (!res.body) {
		throw new Error('SSE response has no body');
	}

	const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();

	// Accumulator for partial lines (SSE data can be split across chunks)
	let buffer = '';

	// Current event being assembled
	let eventId: string | undefined;
	let eventType: string | undefined;
	let dataLines: string[] = [];

	try {
		while (true) {
			const { value, done } = await reader.read();
			if (done) break;

			buffer += value;

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Disable response buffering / SSE-unfriendly compression on any proxy in front of n8n.
  2. Run on a runtime that exposes ReadableStream bodies (modern Node/Deno/browsers).
  3. If reproducible, capture the raw response headers to confirm Content-Type:text/event-stream and presence of a body.
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the response advertises a stream:
const probe = await fetch(url, { headers: { cookie, Accept: 'text/event-stream' }, signal });
if (probe.ok && !probe.body) throw new Error('proxy/runtime swallowed SSE body');

Type guard

const hasReadableBody = (r: Response): r is Response & { body: ReadableStream } =>
  Boolean(r.body);

Prevention

When it happens

Trigger: 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.

Common situations: Reverse proxies buffering SSE; older runtimes where res.body is undefined for streams; misconfigured compression.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/3c76fe60f58f4ed0. Report an issue: GitHub.