danielmiessler/Fabric · error · ChatError

STREAM_CONTENT_ERROR

STREAM_CONTENT_ERROR

Error message

value.content

What it means

While consuming the /api/chat stream, a chunk with { type: 'error', content } makes the reader throw ChatError(content, 'STREAM_CONTENT_ERROR'). The HTTP layer was fine; the backend reported an error mid-stream — typically a failure calling the upstream LLM provider after headers were already sent.

Source

Thrown at web/src/lib/services/ChatService.ts:291

	): Promise<ReadableStream<StreamResponse>> {
		const request = await this.createChatRequest(userInput, systemPromptText);
		return this.fetchStream(request);
	}

	public async processStream(
		stream: ReadableStream<StreamResponse>,
		onContent: (content: string, response?: StreamResponse) => void,
		onError: (error: Error) => void,
	): Promise<void> {
		const reader = stream.getReader();

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

				if (value.type === "error") {
					throw new ChatError(value.content, "STREAM_CONTENT_ERROR");
				}

				if (value.type === "content") {
					onContent(value.content, value);
				}
			}
		} catch (error) {
			onError(
				error instanceof ChatError
					? error
					: new ChatError("Stream processing error", "STREAM_ERROR", error),
			);
		} finally {
			reader.releaseLock();
		}
	}
}

View on GitHub (pinned to 338b89cfe9)

Solutions

  1. Log the value.content of the error event — it carries the backend's upstream error text
  2. If rate-limit/timeout related, add retry with backoff for streams that fail after partial output
  3. Reduce context size or split the request if the upstream rejects it mid-generation
Defensive patterns

Strategy: try-catch

Type guard

function isStreamContentError(e: unknown): e is ChatError & { code: 'STREAM_CONTENT_ERROR' } {
  return e instanceof ChatError && e.code === 'STREAM_CONTENT_ERROR';
}

Try / catch

try {
  await chatService.processStream(stream, onContent, onError);
} catch (e) {
  if (isStreamContentError(e)) {
    keepPartialOutput(); // content already delivered is still valid
    showStreamErrorMessage(e.message);
  } else throw e;
}

Prevention

When it happens

Trigger: Long generations where the vendor API disconnects or rate-limits after the stream began; model context overflow surfacing mid-stream; provider timeout after first tokens; backend panic serialized as an error event.

Common situations: Ollama model OOM-ing on large contexts; API rate limit hit mid-generation; network drop between backend and LLM vendor while the browser-backend connection stays open.

Related errors


AI-assisted analysis of danielmiessler/Fabric@338b89cfe9 (2026-08-15). Data as JSON: /api/errors/7a0e39b699e582e6. Report an issue: GitHub.