fix(streaming): skip SSE events with empty data to prevent JSON parse crash#903
Open
DukeDeSouth wants to merge 1 commit intoanthropics:mainfrom
Open
fix(streaming): skip SSE events with empty data to prevent JSON parse crash#903DukeDeSouth wants to merge 1 commit intoanthropics:mainfrom
DukeDeSouth wants to merge 1 commit intoanthropics:mainfrom
Conversation
… crash
In edge and cloud environments (Vercel Edge, Cloudflare Workers), network
proxies and CDNs can split SSE chunks so that an event line arrives without
its corresponding data line. The SSEDecoder correctly produces an event with
data='', but Stream.fromSSEResponse crashes with "Unexpected end of JSON
input" when trying to JSON.parse('').
This adds an empty-data guard for all event types that expect JSON data:
- completion
- message_start, message_delta, message_stop
- content_block_start, content_block_delta, content_block_stop
Events with empty data are silently skipped, allowing the stream to
continue processing subsequent valid events.
Note: The existing PR anthropics#861 checks `sse.data == null`, which does not
catch this bug since SSEDecoder always sets data to a string (empty
string '' for events without a data line, and '' == null is false).
Fixes anthropics#292 (regression), addresses anthropics#861
Added 16 new tests covering:
- Per-event-type empty data handling (7 event types)
- Stream continuation after empty events
- Interleaved empty and valid events
- Realistic edge-environment simulation
- Error event behavior with empty data
- Abort controller interaction
- All-empty stream completion
- Stress test (100 events with intermittent empty data)
Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Human View
Problem
In edge and cloud environments (Vercel Edge, Cloudflare Workers, AWS Lambda@Edge), network proxies and CDNs can split SSE chunks so that an event line (
event: content_block_delta) arrives without its correspondingdata:line. TheSSEDecodercorrectly produces aServerSentEventwithdata: '', butStream.fromSSEResponsecrashes with:when it calls
JSON.parse('')on the empty data.This is a regression of #292 (originally fixed in v0.17.0 via #312 for
LineDecoder). The root cause is different: theLineDecoderfix ensured correct line splitting, butStream.fromSSEResponsenever had a guard against empty data in the event handlers.Impact
"Unexpected end of JSON input"errors@ts-ignoreor custom patchingRoot Cause
SSEDecoder.decode()accumulates data fromdata:lines and joins them with\n. When an event has nodata:line,this.datais[], and[].join('\n')produces''(empty string).Stream.fromSSEResponsethen blindly callsJSON.parse('')for known event types (completion,message_start,content_block_delta, etc.), which throws.Why PR #861 doesn't fix this
The existing PR #861 checks
sse.data == null, butSSEDecoderalways setsdatato a string value. For events without data,datais''(empty string), and'' == nullevaluates tofalsein JavaScript. The check never triggers.Fix
Added an empty-data guard (
if (!sse.data) continue) beforeJSON.parse()for all event types that expect JSON data:completionmessage_start,message_delta,message_stopcontent_block_start,content_block_delta,content_block_stopThe falsy check
!sse.datacorrectly catches both empty strings ('') and theoretically null/undefined values. Events with empty data are silently skipped, allowing the stream to continue processing subsequent valid events.Tests Added (16 new tests)
APIErrorAll 26 streaming tests pass (10 pre-existing + 16 new).
Checklist
completionand message event handlers!sse.data) instead of null check (== null)SSEDecoderbehavior (SSE spec compliance preserved)APIErroras expectedFixes #292 (regression). Supersedes #861.
AI View (DCCE Protocol v1.0)
Metadata
AI Contribution Summary
Verification Steps Performed
Human Review Guidance
this.dataMade with M7 Cursor