Claude SSE Parse Error During Streaming
Your streaming client fails to parse Server-Sent Events from Claude. Symptoms: JSONDecodeError on partial chunks, missed events, incomplete responses, or hangs when Anthropic sends keep-alive pings. Root cause: custom parsers that don't handle SSE spec properly.
Use the official SDK's stream() method — it handles SSE parsing correctly. If you must write a custom parser: split on \n\n (event boundary), parse event: and data: lines, ignore ping events, and never assume one TCP chunk = one SSE event.
The Error Message You're Seeing
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) → Tried to json.loads() an "event: message_start" line json.decoder.JSONDecodeError: Unterminated string starting at ... → Parsed a chunk that was split mid-JSON across TCP frames TypeError: 'NoneType' object is not subscriptable → Ignored an event type and got None from dict lookup Stream hangs indefinitely → Not handling "ping" keep-alive events, blocking on read UnicodeDecodeError: 'utf-8' codec can't decode byte → Split a multi-byte character across chunks
Understanding Claude's SSE Format
What Actually Causes This Error
\n\n.event: line as JSONOnly the data: line contains JSON. The event: line is the event type.Fixes That Work (Tested Nov 2026)
1Use the SDK's Streaming Helper
2Robust Custom SSE Parser (Python)
3Handle Ping Events and Bytes Correctly
1. Use iter_bytes() then decode UTF-8 after buffering, not per-chunk decode
2. Buffer until you see \n\n — never assume atomicity
3. Only data: lines contain JSON
4. Ignore ping events (or log them if debugging keep-alives)
5. Handle error events explicitly — Anthropic sends these mid-stream on failures
6. The stream ends with message_stop, not connection close
Preventing This Error Going Forward
- Prefer the SDK. It handles all edge cases including reconnection.
- Buffer bytes, decode on event boundaries. Never decode partial chunks.
- Whitelist known event types. Ignore unknown ones for forward compatibility.
- Log ping events count. Useful for debugging network stability.
- Set a read timeout, not just connect. Detect stalled streams.
Researcher · AI Error Hub
Frequently Asked Questions
Keep-alive to prevent proxies (Cloudflare, corporate firewalls) from closing idle connections during long responses. Pings arrive roughly every 15 seconds during model thinking or between content blocks.
Not directly — EventSource doesn't support POST or custom headers. Use fetch() with ReadableStream, or better, proxy through your backend using SSE from server to browser. See our CORS error guide for the pattern.
That's a connection drop. Check for network errors, timeouts, or an error event that arrived before close. The SDK auto-detects and raises; custom parsers should treat premature close as an error and consider retry with same request ID.
Only for very slow consumers. If your loop reads events fast enough, TCP handles it. If you're writing each token to a slow database, buffer or batch instead — Anthropic may close the connection if you're too slow (see streaming-backpressure-timeout error).
Yes, both use the anthropic SDK internally. LangChain's ChatAnthropic.stream() yields message chunks. No SSE handling needed on your side — they abstract it fully.
Related Errors
Master Streaming With Claude
Weekly deep dives on SSE, WebSockets, and real-time LLM UX patterns. 12,000+ developers subscribe.
Subscribe Free →