Skip to content

Fixed OpenAI proxy streaming crash on single-chunk responses - #138

Merged
oleg68 merged 1 commit into
nbplugins:mainfrom
oleg68:bugfix/openai-proxy-streaming-json-escape
May 23, 2026
Merged

oleg68 merged 1 commit into
nbplugins:mainfrom
oleg68:bugfix/openai-proxy-streaming-json-escape

Conversation

@oleg68

@oleg68 oleg68 commented May 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Replaced manual JSON string escaping in StreamingState build* methods with Jackson ObjectNode serialization — the old code missed \b, \f and control characters U+0000–U+001F
  • Added stream_options: {include_usage: true} to outgoing streaming requests so token counts are reported correctly
  • Added defensive buildDoneEvents() call if the backend closes the stream without sending [DONE]

Root cause

When an OpenAI-compatible backend (e.g. gptunnel.ru / deepseek-v4-pro) returns the full response as a single SSE data chunk (pseudo-streaming), the model's reasoning output can contain control characters (\f, \b, etc.). The manual escaping only handled \n, \r, \t, \\, \", so the resulting SSE event contained invalid JSON. Claude Code failed to parse it and exited immediately.

Test plan

  • 858 unit tests pass (mvn test)
  • Configure an OpenAI-compatible proxy profile (e.g. gptunnel.ru / deepseek), start a session, send a prompt — Claude Code should display the response without exiting

Replaced manual JSON string escaping in StreamingState build* methods
with proper Jackson ObjectNode serialization. The old code missed \b, \f
and control characters U+0000–U+001F, producing invalid JSON when model
output (especially reasoning/thinking) contained these characters.
Backends that return the full response as one SSE chunk (pseudo-streaming)
triggered the bug reliably, causing Claude Code to exit immediately.

Also added:
- stream_options: {include_usage: true} in outgoing streaming requests
- Defensive buildDoneEvents() call if backend closes without [DONE]
- doneReceived / isMessageStarted flags on StreamingState
- 8 regression tests covering control-char escaping, single-chunk
  scenario, stream_options, and the doneReceived flag

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@oleg68
oleg68 merged commit f60e180 into nbplugins:main May 23, 2026
3 checks passed
@oleg68
oleg68 deleted the bugfix/openai-proxy-streaming-json-escape branch May 23, 2026 13:21
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