LLM Streaming API Fails or Drops After HTTP 200 OK
Handle mid-stream SSE error events, reverse-proxy buffering/timeout cuts, and unclosed JSON from max_tokens truncation.
Inspect the raw SSE chunks or logs after HTTP 200 OK headers arrive. What happens before the failure?
curl -i -N http://127.0.0.1:11434/v1/chat/completions -H "Content-Type: application/json" -d '{"model":"qwen2.5:7b","stream":true,"messages":[{"role":"user","content":"Hello"}]}'Read Full Reproducible Guide →All 1 Terminal Diagnostic Probes in "LLM Streaming API Fails or Drops After HTTP 200 OK"
Complete static reference of every read-only probe command, baseline hint, and branch transition in this decision tree.
Inspect the raw SSE chunks or logs after HTTP 200 OK headers arrive. What happens before the failure?
curl -i -N http://127.0.0.1:11434/v1/chat/completions -H "Content-Type: application/json" -d '{"model":"qwen2.5:7b","stream":true,"messages":[{"role":"user","content":"Hello"}]}'- • An SSE chunk contains {"error": ...} or type: "error" mid-stream
→ sol-sse-midstream-error-handler - • Connection freezes during long prompt evaluation or drops at exactly 60s
→ sol-proxy-buffering-timeout - • Stream finishes with [DONE], but downstream JSON.parse fails
→ sol-finish-reason-length
3 Verified Root Causes, Fix Configs & Commands in "LLM Streaming API Fails or Drops After HTTP 200 OK"
Fix: Parse In-Stream Error Events Instead of Trusting res.ok Alone
sol-sse-midstream-error-handlerOnce an LLM server flushes HTTP 200 headers to start an SSE stream, it can no longer change the HTTP status code to 500 or 529 if an overload or OOM occurs mid-generation.
- Check every parsed SSE JSON payload for `event.error` or `event.type === "error"` before appending delta text.
- Discard partial corrupted output and trigger a bounded retry with exponential backoff.
const payload = JSON.parse(rawDataLine);
if (payload.error || payload.type === 'error') {
throw new Error(`Mid-stream error after HTTP 200: ${payload.error?.message || JSON.stringify(payload)}`);
}[BOUNDARY]Documented explicitly in Claude API & OpenAI-compatible streaming specifications.
node sse-stream-guard.mjsFix: Disable Proxy Buffering & Increase Read Timeout for Reasoning/Large Prompts
sol-proxy-buffering-timeoutLocal prompt evaluation on 16K+ tokens can take 20–90 seconds before the first token is emitted. Nginx or gateway proxies default to 60s read timeout.
- Set proxy_buffering off and proxy_read_timeout 300s in Nginx / reverse proxy.
- Send periodic SSE keep-alive comments or set client chunk timeout >= 45s.
# Nginx location block for LLM SSE endpoints
location /v1/ {
proxy_pass http://127.0.0.1:11434/v1/;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
chunked_transfer_encoding on;
}[BOUNDARY]Also check Cloudflare Tunnel / proxy 100-second idle timeout if exposing endpoints externally.
nginx -t && sudo systemctl reload nginxFix: Inspect finish_reason === "length" Before Parsing Structured JSON
sol-finish-reason-lengthThe model hit max_tokens (or num_predict) mid-JSON-object. The stream closed cleanly with HTTP 200 and [DONE], leaving half-written JSON.
- Verify choice.finish_reason === "stop" before running JSON.parse.
- For reasoning models (DeepSeek-R1), strip <think>...</think> blocks and budget at least 2048 tokens for output.
if (lastChunk.choices?.[0]?.finish_reason === 'length') {
throw new Error('Output truncated by max_tokens limit before JSON closed');
}[BOUNDARY]Combining response_format: { type: "json_object" } with low max_tokens still truncates if limit is reached!
echo "Verified finish_reason guard"Post-HTTP-200 SSE Stream Errors: Failure Conditions & Recovery Boundaries
Why simple HTTP status-code tables fail in streaming LLM apps: handling mid-stream SSE error events, proxy idle cuts, and max_tokens JSON truncation.
Node.js 22.13+ SSE Client · Applicable to Claude API, OpenAI API, and Local Ollama / vLLM
Node.js 22.13+ · Anthropic Messages SSE · OpenAI Chat Completions SSE
Applies to Both Local & Cloud Streaming APIs — Includes local zero-cost SSE guard client to test your parser against mid-stream error events.