Bug: rate_limit_event injected mid-NDJSON-line in stream-json output, corrupting assistant event parsing
Summary
In Claude Code CLI v2.1.74, rate_limit_event objects are being written to stdout asynchronously in the middle of another NDJSON event (the final assistant message), splitting the line at the rate_limit_event's own \n terminator. This corrupts the stream-json output and causes the assistant response to be silently dropped.
Steps to Reproduce
- Run Claude Code CLI with
--output-format stream-json - Trigger a long response that causes a rate limit notification during generation (e.g., a large text output near the five-hour limit)
- Observe stdout
Observed Behavior
The raw stdout contains a split NDJSON stream:
{"type":"assistant","message":{"content":[{"type":"text","text":"...partial text{"type":"rate_limit_event","rate_limit_info":{"status":"allowed","resetsAt":...},...}
...continuation of text..."}],...},"stop_reason":"end_turn",...}
The rate_limit_event JSON is injected inside the text content of the assistant event, and its own \n terminator splits the outer assistant event's line into two fragments:
- Line 1:
{"type":"assistant",...,"text":"...partial text{"type":"rate_limit_event",...}— fails JSON parsing (unescaped"from rate_limit_event inside text string) - Line 2:
...continuation of text..."}],...}}— not valid JSON (doesn't start with{)
Both lines are unparseable, so the assistant's response text is lost entirely.
Expected Behavior
rate_limit_event should only be emitted at NDJSON line boundaries — i.e., after the current event's \n terminator — never in the middle of another event's output.
Expected stream order:
{"type":"assistant","message":{...full text...},"stop_reason":"end_turn",...}\n
{"type":"rate_limit_event",...}\n
Impact
- Callers using
--output-format stream-jsonreceive an empty response when a rate_limit_event is injected mid-stream - The response text is present in raw stdout bytes but irrecoverable through standard NDJSON line parsing
- In our app, this surfaces as:
"AI 응답이 비어 있습니다 (세션 오류 또는 프로세스 이상)"(empty response error)
Environment
- Claude Code CLI version: 2.1.74
- Output format:
--output-format stream-json - Platform: macOS 15.x
- Observed during: Spark multi-agent round (long text generation, ~3700 output tokens)
Workaround
We implemented a defensive parser fix that:
- Detects
rate_limit_eventinjection within a corrupted line - Removes the injected JSON using balanced-brace traversal
- Saves the partial fragment and joins it with the next line to reconstruct valid JSON
This handles the case but shouldn't be necessary if rate_limit_event is emitted at proper line boundaries.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗