Skip to content

fix(fetch): ignore SSE comment lines instead of ending the stream - #13187

Open
pacocartones wants to merge 1 commit into
continuedev:mainfrom
pacocartones:fix/sse-comment-line-terminates-stream
Open

fix(fetch): ignore SSE comment lines instead of ending the stream#13187
pacocartones wants to merge 1 commit into
continuedev:mainfrom
pacocartones:fix/sse-comment-line-terminates-stream

Conversation

@pacocartones

Copy link
Copy Markdown

Description

parseSseLine returned { done: true } for the : ping keep-alive comment, and streamSse uses that flag to break out of the loop that drains the line buffer.

When a server or proxy flushes the comment in the same chunk as the data: events that follow (common with TCP/TLS coalescing and gateways such as LiteLLM or nginx), those events stay in the buffer. If the stream ends at that point, the trailing-buffer fallback sees a value starting with \n, does not match the data: prefix, and yields nothing — so the remainder of the model response is silently dropped, with no error and no log.

Per the SSE spec, any line starting with a colon is a comment and must be ignored. This changes the branch to match any :-prefixed line and return { done: false }, so the buffer keeps draining.

streamSse is the shared helper behind most providers (OpenAI, Anthropic, Deepseek, Moonshot, VertexAI, LlamaStack, Inception, SiliconFlow, HuggingFace, Cohere), so this affects any of them talking to a server that sends SSE comments.

AI Code Review

  • Team members only: AI review runs automatically when PR is opened or marked ready for review
  • Team members can also trigger a review by commenting @continue-review

Checklist

  • I've read the contributing guide
  • The relevant docs, if any, have been updated or created
  • The relevant tests, if any, have been updated or created

Screen recording or screenshot

Not applicable — no user-facing UI change. The behaviour is covered by the unit test below.

Tests

Added ignores SSE comment lines that share a chunk with data events to packages/fetch/src/stream.test.ts. It pushes a single chunk containing : ping followed by two data: events and data: [DONE].

Before the fix the test fails with expected [] to deeply equal [ { foo: 'bar' }, { baz: 42 } ] — the entire response is lost. After the fix both events are yielded.

npx vitest run in packages/fetch: 6 files, 83 tests passing.

parseSseLine treated a `: ping` keep-alive as done: true, which breaks out of
the line loop in streamSse. When a server or proxy flushes that comment in the
same chunk as the data events that follow, those events are left in the buffer
and the trailing-buffer fallback cannot parse them, so the rest of the model
response is silently dropped.

Per the SSE spec any line starting with a colon is a comment and must be
ignored, so return done: false for it and keep draining the buffer.
@pacocartones
pacocartones requested a review from a team as a code owner August 24, 2026 08:00
@pacocartones
pacocartones requested review from sestinj and removed request for a team August 24, 2026 08:00
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