[BUG] Synthetic rate_limit error returned with 0 input/output tokens on main agent despite low usage and extended idle periods
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 v2.1.86, Opus 4.6
- model=<synthetic> with service_tier=None — never reaches the real API
- input_tokens=0, output_tokens=0 — zero processing
- Occurs on agent=main, not just subagents
- 21% plan usage at time of error
- Occurs after gaps of 25 min, 54 min, and even 11 hours
- Main conversation works seconds later (same session, same context)
- cache_read_input_tokens: 918,977 on successful calls — large context may be relevant
What Should Happen?
When a user sends a message at 21% plan usage with no concurrent requests and hours of idle time, the API should process the request normally — not
return a synthetic rate_limit error with 0 tokens. Specifically:
- The request should reach the actual API (not be intercepted as model=<synthetic>)
- A service_tier should be assigned (not None)
- Tokens should be consumed and a response generated
- If a legitimate rate limit exists, the error should include: which limit was hit, when it resets, and current usage — not a generic "Rate limit
reached" with zero diagnostic information
- An 11-hour idle period should be more than sufficient to reset any per-minute or per-hour throughput limit
Error Messages/Logs
# Claude Code Rate Limit Bug — Full Log Evidence
# Version: Claude Code 2.1.86
# Model: claude-opus-4-6 (1M context)
# Plan usage at time of errors: 21%
# Platform: Linux 6.17.0-19-generic (Ubuntu)
## RATE LIMIT ERRORS (all from session JSONL log)
## Format: timestamp | agent | model | input_tokens | output_tokens | cache_read | cache_create | service_tier | error
# === March 25 ===
2026-03-25T14:27:03.556Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | "You've hit your limit · resets 12pm (America/Chicago)"
# === March 27 ===
2026-03-27T15:08:37.493Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | "You've hit your limit · resets 11am (America/Chicago)"
# === March 28 (8 errors, gaps of 20-90 minutes between attempts) ===
2026-03-28T12:17:17.013Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | "API Error: Rate limit reached"
2026-03-28T12:27:31.672Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | "API Error: Rate limit reached"
2026-03-28T14:52:06.576Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | (147 min gap)
2026-03-28T14:52:12.024Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit
2026-03-28T15:23:45.457Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | (31 min gap)
2026-03-28T15:28:52.507Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit
2026-03-28T15:48:07.080Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | (20 min gap)
2026-03-28T16:14:31.230Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | (26 min gap)
# === March 29 (12 errors, including an 11-HOUR gap that still gets rejected) ===
2026-03-29T00:56:35.936Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | (9 HOUR gap from last error)
2026-03-29T00:56:40.041Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit
2026-03-29T00:57:50.254Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit
2026-03-29T03:51:50.608Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | (3 HOUR gap)
2026-03-29T03:51:55.065Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit
2026-03-29T04:46:07.221Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | (54 min gap)
2026-03-29T04:46:16.160Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit
2026-03-29T04:46:48.965Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit
2026-03-29T04:50:31.034Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit
2026-03-29T04:51:42.804Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit
2026-03-29T05:03:01.889Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit | (12 min gap)
2026-03-29T05:03:35.017Z | agent=main | model=<synthetic> | in=0 out=0 | cache_r=0 cache_c=0 | tier=None | err=rate_limit
## SUCCESSFUL CALLS (same session, seconds after rate limit errors)
## Proves the main conversation works fine — the rate limit is spurious
2026-03-29T05:08:24.367Z | agent=main | model=claude-opus-4-6 | in=1 out=225 | cache_r=918977 cache_c=375 | tier=standard | SUCCESS
2026-03-29T05:08:44.373Z | agent=main | model=claude-opus-4-6 | in=1 out=301 | cache_r=920004 cache_c=584 | tier=standard | SUCCESS
2026-03-29T05:08:55.261Z | agent=main | model=claude-opus-4-6 | in=1 out=266 | cache_r=920588 cache_c=1250 | tier=standard | SUCCESS
## KEY OBSERVATIONS
# 1. ALL rate limit errors show model=<synthetic> — request never reaches real API
# 2. ALL show service_tier=None — no tier assigned
# 3. ALL show input_tokens=0, output_tokens=0 — zero processing
# 4. ALL are on agent=main — not subagent/background work
# 5. Gaps between errors: 20min, 31min, 54min, 3hrs, 9hrs, 11hrs — still rejected
# 6. Plan usage dashboard shows 21% at time of errors
# 7. Successful calls (same session) show cache_read=918K+ tokens — large context
# 8. No concurrent requests running during most failures
# 9. Affects both direct user messages AND subagent spawns equally
## RAW JSONL SAMPLE (one rate limit + one success for comparison)
# Rate limit (synthetic, 0 tokens, no tier):
{"timestamp":"2026-03-29T04:46:07.221Z","message":{"id":"54dd0bfd-c56e-4634-b09a-c45cc8351e5a","container":null,"model":"<synthetic>","role":"assistant","stop_reason":"stop_sequence","stop_sequence":"","type":"message","usage":{"input_tokens":0,"output_tokens":0,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":null,"cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"inference_geo":null,"iterations":null,"speed":null},"content":[{"type":"text","text":"API Error: Rate limit reached"}],"context_management":null},"error":"rate_limit"}
# Success (real model, real tokens, real tier — 22 minutes later, same session):
{"timestamp":"2026-03-29T05:08:24.367Z","message":{"model":"claude-opus-4-6","id":"msg_...","type":"message","role":"assistant","usage":{"input_tokens":1,"cache_creation_input_tokens":375,"cache_read_input_tokens":918977,"output_tokens":225,"service_tier":"standard"},"content":[{"type":"tool_use",...}]}}
## ENVIRONMENT
# Claude Code version: 2.1.86
# Model: claude-opus-4-6 (Opus 4.6 with 1M context)
# OS: Linux 6.17.0-19-generic (Ubuntu)
# Session context: ~920K cached tokens (large codebase, long session)
# Plan: Max (showing 21% usage)
# Settings: {"env":{"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS":"1"},"effortLevel":"high"}
Steps to Reproduce
- Open Claude Code v2.1.86 on the Max plan at ~21% usage
- Work in a large codebase session until context cache reaches ~900K+ tokens
- Spawn a subagent using the Agent tool (any task)
- Observe: subagent returns API Error: Rate limit reached with 0 tokens processed
- Wait 20+ minutes, try again — same error
- Wait 11+ hours, try again — same error
- Send a direct message (not subagent) — it works fine with model=claude-opus-4-6, service_tier=standard, and 918K+ cache_read tokens
- Try spawning another subagent — rate limit error again with model=<synthetic>, 0 tokens
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.86
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Xterm
Additional Information
- This session has been running for ~6 days continuously (started 2026-03-23), producing 950+ file changes, 200+ database migrations, and spawning 100+
successful subagents before the rate limiting began
- The first 4 days of the session had zero rate limit issues with heavy parallel agent usage (up to 4 concurrent subagents)
- Rate limit errors began appearing on day 5 (March 28) and became persistent on day 6 (March 29)
- The session JSONL file is 13.5MB — the growing session context may be a factor
- cache_read_input_tokens on successful calls is 918,977 — near the 1M context ceiling
- The <synthetic> model tag suggests Claude Code is generating the error locally rather than receiving a 429 from the API — unclear if the request ever
leaves the client
- CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 is enabled — this may affect how agent token budgets are allocated
- effortLevel: "high" is set in settings.json
- Restarting Claude Code (/exit and relaunch) temporarily resolves the issue for a few interactions, then it returns — suggesting client-side state
accumulation
Questions for the team:
- Does model=<synthetic> mean the rate limit is enforced client-side before the API call, or is the API returning this?
- Is there a separate token budget for subagents vs the main conversation?
- Does cache_read_input_tokens near 920K count toward rate limits differently than fresh input tokens?
- Is there a per-session or per-day ceiling that isn't reflected in the usage dashboard?
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗