Bug: rate_limit_event injected mid-NDJSON-line in stream-json output, corrupting assistant event parsing

Resolved 💬 1 comment Opened Apr 17, 2026 by DillanK Closed May 27, 2026

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

  1. Run Claude Code CLI with --output-format stream-json
  2. Trigger a long response that causes a rate limit notification during generation (e.g., a large text output near the five-hour limit)
  3. 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-json receive 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:

  1. Detects rate_limit_event injection within a corrupted line
  2. Removes the injected JSON using balanced-brace traversal
  3. 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.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗