fix(gateway): single-newline SSE keepalive - #2334
Conversation
The `: ping\n\n` keepalive emitted a blank line that openai-python's SSEDecoder treats as an event dispatch once last_event_id is set, producing an empty-data event that crashes sse.json() (openai/openai-python#2722). Drop the trailing newline so the comment is no longer followed by a blank line. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe chat streaming SSE keepalive mechanism is modified to write a single-line comment ( ChangesSSE Keepalive Ping Format
Estimated code review effort🎯 2 (Simple) | ⏱️ ~5 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Fixes an SSE keepalive bug where : ping\n\n triggered buggy SSE parsers (openai-python ≤ 2.37.0) to dispatch an empty-data event and raise JSONDecodeError. Changing to a single \n keeps the comment valid and still flushes bytes for proxy keepalive without producing a blank line.
Changes:
- Replace
": ping\n\n"with": ping\n"in the chat-streaming keepalive interval - Update the accompanying comment to explain the rationale
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Thank you so much! |
Summary
The chat-streaming keepalive emits
: ping\n\nevery 15s. The trailing\n\nis a comment followed by a blank line — and the openai-python SSE decoder dispatches an event on any blank line as long aslast_event_idwas set by an earlier real event (which it always is, since the gateway setsid:on every chunk). The dispatched event hasevent=None, data='', andsse.json()then raisesJSONDecodeError.This explains the report at openai/openai-python#2722 and matches the observed timing: Claude generations slow enough to still be streaming when the first 15s keepalive fires crash ~16-17s in; faster generations (DeepSeek) finish before any keepalive and never trip it.
Fix: drop the trailing newline.
: ping\nis still a valid SSE comment line and still flushes bytes for proxy keepalive, but no blank line follows, so no buggy parser dispatches an empty-data event. Spec-compliant parsers behave identically.Test plan
JSONDecodeErrorafter 15spnpm test:unitclean🤖 Generated with Claude Code
Summary by CodeRabbit