[BUG] Client-side synthetic rate limit fires after just 4 rapid tool calls (model="<synthetic>", usage=0)

Resolved 💬 3 comments Opened Mar 13, 2026 by qijianfky Closed Mar 16, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code fires a client-side synthetic "API Error: Rate limit reached" after only 4 consecutive tool calls within a few seconds. The request never reaches the Anthropic API — confirmed by inspecting the session JSONL:

{
  "model": "<synthetic>",
  "isApiErrorMessage": true,
  "error": "rate_limit",
  "usage": {
    "input_tokens": 0,
    "output_tokens": 0,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 0
  }
}

Plan usage at the time: session 2%, weekly 24% — nowhere near any limit.

This is not the same as #25531 (compact-related) or #29579 (auth/subscription). This is a client-side throttle that fires during normal interactive use when the model happens to issue a few tool calls in quick succession.

What Should Happen?

4 tool calls in a few seconds should not trigger rate limiting, especially when plan usage is at 2%. If client-side throttling is intentional, it should:

  1. Have a higher threshold (4 calls is too aggressive)
  2. Display a distinct error message (e.g. "Client-side throttle — retrying in Xs") instead of the misleading "API Error: Rate limit reached" which implies an API-side 429
  3. Auto-retry with backoff instead of surfacing the error to the user

Error Messages/Logs

API Error: Rate limit reached

Full synthetic message from session JSONL (e8ff8b9f-d84e-44eb-80f3-9357168880fe.jsonl, line 39):

{
  "type": "assistant",
  "message": {
    "model": "<synthetic>",
    "role": "assistant",
    "stop_reason": "stop_sequence",
    "usage": { "input_tokens": 0, "output_tokens": 0 },
    "content": [{ "type": "text", "text": "API Error: Rate limit reached" }]
  },
  "error": "rate_limit",
  "isApiErrorMessage": true
}

Steps to Reproduce

  1. Start a Claude Code session (bypassPermissions mode)
  2. Have the model issue 4+ tool calls in rapid succession (e.g. TaskOutput → Bash → Bash → Read)
  3. The 4th call triggers a synthetic rate limit error
  4. Sequence from the session log:
  • Line 33: TaskOutput (failed — task not found)
  • Line 35: Bash (tail command)
  • Line 37: Bash (ls command)
  • Line 39: → synthetic rate limit error (never reached API)

Claude Model

Opus 4.6 (1M context)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.74

Platform

macOS (darwin)

Operating System

macOS Darwin 25.2.0

Terminal/Shell

zsh

Additional Information

This is particularly problematic for orchestration use cases where Claude Code drives multi-agent workflows (e.g. a "code factory" that spawns parallel agents). Monitoring those workflows requires periodic polling via tool calls, and hitting a client-side rate limit after just 4 calls makes this workflow fragile.

The misleading error message ("API Error: Rate limit reached") caused significant debugging time — we initially suspected API-side rate limits, plan quota exhaustion, or interference from concurrent agents, before discovering the model: "<synthetic>" field in the JSONL proving it was client-side.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗