Skip to content

fix: skip empty-data SSE events per HTML5 spec#651

Open
Chronostasys wants to merge 1 commit into
openai:mainfrom
Chronostasys:fix/sse-empty-event-filter
Open

fix: skip empty-data SSE events per HTML5 spec#651
Chronostasys wants to merge 1 commit into
openai:mainfrom
Chronostasys:fix/sse-empty-event-filter

Conversation

@Chronostasys

Copy link
Copy Markdown

Problem

Some LLM providers (e.g. Xiaomi MiMo) send keep-alive comments during streaming:

: PROCESSING

This produces an SSE event with empty Data. The current eventStreamDecoder.Next() dispatches it, and Stream[T].Next() then calls json.Unmarshal([]byte{}, ...) which returns "unexpected end of JSON input" — crashing the stream.

Root Cause

The HTML5 SSE specification states:

If the data buffer is an empty string, set the data buffer and the event type buffer to the empty string and return.

Events with empty data should be silently discarded. The current implementation dispatches them regardless.

Fix

In eventStreamDecoder.Next(), when a blank line triggers event dispatch, check if data.Len() == 0. If so, reset state and continue instead of returning the empty event.

Testing

Added ssestream_test.go with 5 test cases:

  • Comment-only event is skipped
  • Multiple comments before data are skipped
  • Multiple data events are preserved
  • Stream-level integration: comment + data works end-to-end
  • Comment-only stream produces no events and no error

All tests pass.

Compatibility

  • Normal OpenAI/Anthropic streams: no change (they never send empty-data events)
  • Providers using SSE comments as keep-alive: now work correctly
  • No API changes, fully backward compatible

@Chronostasys Chronostasys requested a review from a team as a code owner April 28, 2026 07:37
Some LLM providers (e.g. Xiaomi MiMo) send keep-alive comments like
': PROCESSING\n\n' during streaming. The empty line dispatches an event
with empty data, which json.Unmarshal then fails on with 'unexpected end
of JSON input'.

Per the HTML5 SSE specification, events with empty data buffers should
be silently discarded. This patch adds a data.Len() == 0 check in
eventStreamDecoder.Next() to skip such events instead of dispatching them.

Fixes compatibility with providers that use SSE comments as keep-alive
signals during model processing.
@Chronostasys Chronostasys force-pushed the fix/sse-empty-event-filter branch from a19c262 to a655caf Compare April 28, 2026 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant