Skip to content

[BUG] Client-side rate limiter blocks requests with zero API calls when conversation transcript is large (~74MB) — false rate_limit error with synthetic model and 0 input/output tokens #40584

Closed as not planned

Description

@rwp65

Preflight Checklist

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

What's Wrong?

After hours of inactivity in a long-running session, every new message from the user immediately returns "API Error: Rate limit reached" without making any API call. The error is generated client-side by Claude Code, not by the Anthropic API. The user cannot proceed with any work — every message, including simple ones like "proceed", triggers the same error.

What Should Happen?

After hours of inactivity, the rate limit budget should have fully reset. A simple message should be sent to the API and receive a normal response.

Error Messages/Logs

Session log: `~/.claude/projects/-home-rich-RE6D/7137463d-be5d-4d5e-a97d-bb12b5e44b58.jsonl`

**Six consecutive blocked requests between 13:11:09 and 13:11:28 UTC on 2026-03-29:**

Each error entry has this structure:


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


Key observations:

| Field | Value | Significance |
|-------|-------|-------------|
| `model` | `"<synthetic>"` | NOT a real API response — generated by Claude Code client |
| `input_tokens` | `0` | No tokens were sent to the API |
| `output_tokens` | `0` | No tokens were received from the API |
| `cache_read_input_tokens` | `0` | No cache was accessed |
| `isApiErrorMessage` | `true` | Claude Code flagged this as an API error |
| `error` | `"rate_limit"` | Client-side classification |

**Contrast with the first successful request after the user persisted (13:11:37 UTC):**


{
  "model": "claude-opus-4-6",
  "usage": {
    "input_tokens": 3,
    "cache_creation_input_tokens": 1315,
    "cache_read_input_tokens": 668864,
    "output_tokens": 1,
    "service_tier": "standard"
  }
}

Steps to Reproduce

  1. Run a Claude Code session for multiple days with heavy agent usage (many subagent dispatches, large code changes)
  2. Accumulate a conversation transcript of ~74MB (the .jsonl file grows as the session continues)
  3. Leave the session idle for several hours
  4. Send any message (e.g., "proceed")
  5. Observe: immediate "API Error: Rate limit reached" with no actual API call

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

No response

Claude Code Version

2.1.81

Platform

Anthropic API

Operating System

Other Linux

Terminal/Shell

Xterm

Additional Information

Bug Report: Client-side rate limiter blocks requests with zero API calls when conversation transcript is large

Title

Client-side rate limiter blocks requests with zero API calls when conversation transcript is large (~74MB) — false rate_limit error with synthetic model and 0 input/output tokens

Environment

  • Claude Code Version: 2.1.81
  • OS: Ubuntu Linux 6.17.0-19-generic
  • Shell: bash
  • Model: claude-opus-4-6 (1M context)
  • Platform: CLI (entrypoint: "cli")
  • Session ID: 7137463d-be5d-4d5e-a97d-bb12b5e44b58

Description

After hours of inactivity in a long-running session, every new message from the user immediately returns "API Error: Rate limit reached" without making any API call. The error is generated client-side by Claude Code, not by the Anthropic API. The user cannot proceed with any work — every message, including simple ones like "proceed", triggers the same error.

Steps to Reproduce

  1. Run a Claude Code session for multiple days with heavy agent usage (many subagent dispatches, large code changes)
  2. Accumulate a conversation transcript of ~74MB (the .jsonl file grows as the session continues)
  3. Leave the session idle for several hours
  4. Send any message (e.g., "proceed")
  5. Observe: immediate "API Error: Rate limit reached" with no actual API call

Expected Behavior

After hours of inactivity, the rate limit budget should have fully reset. A simple message should be sent to the API and receive a normal response.

Actual Behavior

Claude Code's client-side rate limiter blocks the request before it reaches the Anthropic API. The user sees "API Error: Rate limit reached" and cannot use the tool at all.

Evidence from Logs

Session log: ~/.claude/projects/-home-rich-RE6D/7137463d-be5d-4d5e-a97d-bb12b5e44b58.jsonl

Six consecutive blocked requests between 13:11:09 and 13:11:28 UTC on 2026-03-29:

Each error entry has this structure:

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

Key observations:

Field Value Significance
model "<synthetic>" NOT a real API response — generated by Claude Code client
input_tokens 0 No tokens were sent to the API
output_tokens 0 No tokens were received from the API
cache_read_input_tokens 0 No cache was accessed
isApiErrorMessage true Claude Code flagged this as an API error
error "rate_limit" Client-side classification

Contrast with the first successful request after the user persisted (13:11:37 UTC):

{
  "model": "claude-opus-4-6",
  "usage": {
    "input_tokens": 3,
    "cache_creation_input_tokens": 1315,
    "cache_read_input_tokens": 668864,
    "output_tokens": 1,
    "service_tier": "standard"
  }
}

This successful request shows cache_read_input_tokens: 668,864 — the session context is approximately 668K tokens. This is likely what the client-side rate limiter is counting against the budget.

Root Cause Hypothesis

The client-side rate limiter appears to calculate the token cost of the next request by estimating the context size (668K+ tokens) and checking it against a per-minute or per-hour token budget. For very large sessions, the CONTEXT ALONE may exceed the rate limit budget — even though the user's actual message is just a few tokens.

This creates a situation where:

  • The session grows over days of heavy use
  • The context window fills with conversation history
  • Eventually the context size exceeds the rate limit's per-window token budget
  • Every subsequent request is blocked client-side, regardless of actual API availability
  • The user is permanently locked out until they start a new session

Session Size Data

Metric Value
Session transcript file 74,019,933 bytes (74MB)
Estimated context tokens 668,864 (from cache_read_input_tokens)
Session duration ~4 days (2026-03-25 to 2026-03-29)
Subagents dispatched 50+ over the session
Session compactions Multiple (context was compressed during the session)

Impact

  • Severity: High — user is completely blocked from using Claude Code
  • Workaround: Start a new session (loses all conversation context)
  • User experience: Extremely frustrating — the error message gives no indication that the session size is the problem, and retrying makes it worse (each retry attempt may count against the budget)

Suggested Fix

  1. Don't count cached/context tokens against the rate limit budget — the user isn't "using" more tokens by having a long session. The cache is already paid for.
  2. If rate limiting must include context, reset the budget after idle periods — hours of inactivity should fully reset any per-minute/per-hour budget.
  3. Show a more helpful error message — instead of "API Error: Rate limit reached", show "Session context is very large (668K tokens). Consider starting a new session with /compact or a fresh session."
  4. Distinguish client-side rate limiting from API rate limiting — the current message is identical for both, making it impossible for the user to diagnose.

Activity

  1. github-actions commented on Mar 29, 2026

    @github-actions

    Found 3 possible duplicate issues:

    1. [BUG] Synthetic rate_limit error returned with 0 input/output tokens on main agent despite low usage and extended idle periods #40485
    2. [BUG] Client-side synthetic rate limit fires after just 4 rapid tool calls (model="<synthetic>", usage=0) #33840
    3. Session permanently stuck on 'Rate limit reached' after transient rate limit #26699

    This issue will be automatically closed as a duplicate in 3 days.

    • If your issue is a duplicate, please close it and 👍 the existing issue instead
    • To prevent auto-closure, add a comment or 👎 this comment

    🤖 Generated with Claude Code

  2. rwp65 commented on Mar 29, 2026

    @rwp65
    Author

    updated information:

    Bug Report: Client-side rate limiter blocks requests with zero API calls — false rate_limit error

    Title

    Client-side rate limiter generates false rate_limit errors with model: "<synthetic>" and input_tokens: 0 — no API call made. Triggered by BOTH large transcripts AND concurrent subagent spawns.

    Environment

    • Claude Code Version: 2.1.81
    • OS: Ubuntu Linux 6.17.0-19-generic
    • Shell: bash
    • Model: claude-opus-4-6 (1M context)
    • Platform: CLI (entrypoint: "cli")
    • Session ID: 7137463d-be5d-4d5e-a97d-bb12b5e44b58

    Description

    After hours of inactivity in a long-running session, every new message from the user immediately returns "API Error: Rate limit reached" without making any API call. The error is generated client-side by Claude Code, not by the Anthropic API. The user cannot proceed with any work — every message, including simple ones like "proceed", triggers the same error.

    Steps to Reproduce

    1. Run a Claude Code session for multiple days with heavy agent usage (many subagent dispatches, large code changes)
    2. Accumulate a conversation transcript of ~74MB (the .jsonl file grows as the session continues)
    3. Leave the session idle for several hours
    4. Send any message (e.g., "proceed")
    5. Observe: immediate "API Error: Rate limit reached" with no actual API call

    Expected Behavior

    After hours of inactivity, the rate limit budget should have fully reset. A simple message should be sent to the API and receive a normal response.

    Actual Behavior

    Claude Code's client-side rate limiter blocks the request before it reaches the Anthropic API. The user sees "API Error: Rate limit reached" and cannot use the tool at all.

    Evidence from Logs

    Session log: ~/.claude/projects/-home-rich-RE6D/7137463d-be5d-4d5e-a97d-bb12b5e44b58.jsonl

    Six consecutive blocked requests between 13:11:09 and 13:11:28 UTC on 2026-03-29:

    Each error entry has this structure:

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

    Key observations:

    Field Value Significance
    model "<synthetic>" NOT a real API response — generated by Claude Code client
    input_tokens 0 No tokens were sent to the API
    output_tokens 0 No tokens were received from the API
    cache_read_input_tokens 0 No cache was accessed
    isApiErrorMessage true Claude Code flagged this as an API error
    error "rate_limit" Client-side classification

    Contrast with the first successful request after the user persisted (13:11:37 UTC):

    {
      "model": "claude-opus-4-6",
      "usage": {
        "input_tokens": 3,
        "cache_creation_input_tokens": 1315,
        "cache_read_input_tokens": 668864,
        "output_tokens": 1,
        "service_tier": "standard"
      }
    }

    This successful request shows cache_read_input_tokens: 668,864 — the session context is approximately 668K tokens. This is likely what the client-side rate limiter is counting against the budget.

    Root Cause Hypothesis

    The client-side rate limiter appears to calculate the token cost of the next request by estimating the context size (668K+ tokens) and checking it against a per-minute or per-hour token budget. For very large sessions, the CONTEXT ALONE may exceed the rate limit budget — even though the user's actual message is just a few tokens.

    This creates a situation where:

    • The session grows over days of heavy use
    • The context window fills with conversation history
    • Eventually the context size exceeds the rate limit's per-window token budget
    • Every subsequent request is blocked client-side, regardless of actual API availability
    • The user is permanently locked out until they start a new session

    Session Size Data

    Metric Value
    Session transcript file 74,019,933 bytes (74MB)
    Estimated context tokens 668,864 (from cache_read_input_tokens)
    Session duration ~4 days (2026-03-25 to 2026-03-29)
    Subagents dispatched 50+ over the session
    Session compactions Multiple (context was compressed during the session)

    Impact

    • Severity: High — user is completely blocked from using Claude Code
    • Workaround: Start a new session (loses all conversation context)
    • User experience: Extremely frustrating — the error message gives no indication that the session size is the problem, and retrying makes it worse (each retry attempt may count against the budget)

    Second Occurrence — Concurrent Subagent Trigger (Same Session Day, Different Session)

    Session ID: 13d72e07-75c2-49af-9463-6cd2b57528a7
    Timestamp: 2026-03-29T21:15:06.774Z

    What Happened

    User dispatched 3 Opus subagents in parallel using the Agent tool. All 3 returned "API Error: Rate limit reached" immediately. The main session was working normally — the rate limit only hit the subagent spawns.

    Evidence from Logs

    Same signature as Occurrence 1:

    {
      "model": "<synthetic>",
      "input_tokens": 0,
      "output_tokens": 0,
      "timestamp": "2026-03-29T21:15:06.774Z"
    }

    Session Size Data — MUCH SMALLER Than Occurrence 1

    Metric Occurrence 1 Occurrence 2
    Session transcript 74 MB 2.9 MB
    Estimated context tokens 668K Unknown (not in log)
    Subagent log files 50+ 28
    Total subagent log size N/A 3.9 MB
    Total messages N/A 957
    Session duration ~4 days ~8 hours
    Trigger Single user message after idle 3 concurrent Agent tool calls

    Critical Finding

    This is NOT a transcript size issue. The session was 2.9 MB (vs 74 MB) — 25x smaller. The trigger was spawning 3 subagents simultaneously. Each subagent inherits the parent conversation context and makes its own API call. The client-side rate limiter appears to calculate:

    3 agents × estimated_context_tokens = total_tokens_in_flight
    

    If this exceeds the per-minute token budget, all 3 are blocked — even though each individual request would be fine.

    Additional Context

    • The main session continued working normally after the subagent failures
    • 12 prior subagent dispatches in this session all succeeded (some in parallel pairs)
    • The failure occurred after ~8 hours and ~957 messages of accumulated context
    • Prior successful parallel dispatches were earlier in the session when context was smaller

    Updated Root Cause Hypothesis

    The client-side rate limiter multiplies estimated context tokens by the number of concurrent requests. For a session with ~400K context tokens:

    • 1 request: 400K tokens → under budget → succeeds
    • 2 requests: 800K tokens → may be under budget → usually succeeds
    • 3 requests: 1.2M tokens → exceeds budget → all blocked

    This creates a progressive degradation: as the session grows, fewer concurrent agents can be spawned before hitting the false limit. Eventually even a single request may be blocked (Occurrence 1).

    Suggested Fix

    1. Don't multiply context tokens by concurrent request count — the context is cached and shared. Sending 3 requests with the same 400K context doesn't cost 1.2M tokens.
    2. If rate limiting must account for concurrency, use actual API token consumption — not estimated context size. The API response includes actual usage in cache_read_input_tokens.
    3. Show a more helpful error message — instead of "API Error: Rate limit reached", show "Too many concurrent requests for current context size. Try running agents sequentially or starting a fresh session."
    4. Distinguish client-side rate limiting from API rate limiting — the current message is identical for both, making it impossible for the user to diagnose.
    5. Log the rate limiter's calculation — include estimated_tokens, budget_remaining, concurrent_requests in the log entry so users can understand WHY they were blocked.
  3. marlvinvu commented on Apr 2, 2026

    @marlvinvu

    My Claude says your finding — both occurrences — may be the root cause for dozens of unexplained rate limit issues: #38239, #37917, #39465, #39938, #40079, #40085, #40128, #40273, #40438, #40504, #40532. The evidence of model: "" with input_tokens: 0 is the smoking gun — proving the request was NEVER sent to the API. And your second finding is even more important: the rate limiter multiplies context × concurrent requests — explaining why multi-agent workflows get blocked even though each individual request is within budget. I've commented on those issues linking to yours so they know. Thank you for analyzing the logs this thoroughly — this is forensic work that Anthropic should read carefully.

  4. ArkNill commented on Apr 3, 2026

    @ArkNill

    Adding independent confirmation from a different setup.

    I scanned all session JSONL files on my machine (Max 20, v2.1.90-91, Linux) for <synthetic> model entries:

    • 151 <synthetic> entries across 65 session files
    • 25 of those in acompact sub-agents (compaction processes hitting the false rate limiter)
    • 126 in regular sessions

    Example entry from our logs:

    {"model": "<synthetic>", "usage": {"input_tokens": 0, "output_tokens": 0}, "stop_reason": "stop_sequence"}

    This isn't a rare edge case — it's happening routinely. The acompact sub-agent hits are particularly concerning because they mean the compaction process itself gets blocked by the client-side rate limiter, potentially leaving sessions in a degraded state.

    Tested on v2.1.91: no fix mentioned in changelog, and the underlying rate limiter logic (context_size × concurrent_requests) hasn't changed.

    @rwp65 Your original analysis was spot-on. This is one of several unfixed bugs we've been tracking across the rate limit issues — documented at claude-code-cache-analysis as Bug 3 in the 6-layer model.

  5. dancinlife commented on Apr 3, 2026

    @dancinlife

    How we identified and mitigated rate limit bugs — full operational report

    @dliedke This bug (false rate limiter) is confirmed still present in v2.1.91. Here's what we've built to work around the full set of rate limit issues, including this one.

    Our monitoring setup

    We run 9 MAX accounts with a custom launcher (ccmon) that tracks real-time usage via the OAuth usage API. This is what our dashboard looks like:

    Image

    What we discovered through multi-account monitoring

    By watching utilization patterns across 9 accounts simultaneously, we identified contamination vectors that silently link accounts:

    claude login doesn't clear oauthAccount in .claude.json — the previous account's accountUuid persists into the new config. This causes:

    1. Server-side org grouping (Rate limit quota is shared per organizationUuid, not per account #41886) — accounts sharing leaked UUIDs get pooled into one rate limit
    2. Cache field accumulation — groveConfigCache, passesEligibilityCache, overageCreditGrantCache pile up foreign UUIDs

    Contamination vectors we've mapped

    # Vector Risk Our fix
    1 claude login not clearing oauthAccount ❌ Root cause of org-grouping Auto-clean oauthAccount + 3 cache fields before login
    2 Sharing .claude.json across config dirs ❌ Dangerous Never symlink — only settings.json is safe
    3 Symlinking entire projects/ directory ❌ Dangerous Per-project memory/ symlinks only
    4 Env file sharing across terminal tabs 🔧 Fixed PID-scoped env files (~/.claude-env-{PID})
    5 Sourcing last-used env in .zshrc ❌ Dangerous Every new shell inherits last account
    6 False rate limiter (<synthetic> entries) ❌ This issue Start fresh sessions; no client-side fix possible

    Remaining bugs after v2.1.91 cache fix

    The cache regression fix was significant — 95-99% cache read restored. But 4 bugs still cause unexpected consumption:

    Full measured data: claude-code-cache-analysis

  6. junaidtitan commented on Apr 3, 2026

    @junaidtitan

    A 74MB transcript triggering the client-side rate limiter is a session size problem. Cozempic v1.4.1 can dramatically shrink these files — the aggressive prescription runs 17 strategies that target every bloat type.

    For a session that size: cozempic treat <session> -rx aggressive --execute

    Or install the guard daemon for automatic prevention:

    pip install cozempic && cozempic init

    compact-summary-collapse alone saves 85-95% on compacted sessions. Combined with image-strip, progress-collapse, and document-dedup, you should see that 74MB drop to single-digit MB.

  7. junaidtitan commented on Apr 6, 2026

    @junaidtitan

    74MB transcript triggering the false rate limit is a session size problem. Cozempic v1.6.11 can dramatically reduce that — aggressive prescription runs 18 strategies. compact-summary-collapse alone saves 85-95%. The guard daemon prevents files from ever reaching that size.

    pip install cozempic && cozempic init

  8. rwp65 commented on Apr 10, 2026

    @rwp65
    Author

    ANTHROPIC - WHY HAS THIS NOT BEEN ASSIGNED TO SOMEONE TO FIX??????????

  9. github-actions commented on May 24, 2026

    @github-actions

    Closing for now — inactive for too long. Please open a new issue if this is still relevant.

  10. github-actions commented on Jul 16, 2026

    @github-actions

    This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.

  11. locked as resolved and limited conversation to collaborators on Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:corebugSomething isn't workinghas reproHas detailed reproduction stepsstaleIssue is inactive

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions