Rate limit errors show 'API Error' without distinguishing usage vs throughput limits

Resolved 💬 31 comments Opened Feb 14, 2026 by techbantu Closed Jun 4, 2026

Problem

Users on paid plans (including Pro Max $200/month) are encountering API Error: Rate limit reached messages when their usage dashboard shows they haven't hit their limits. This creates confusion and disrupts workflow because the error message doesn't clarify what limit was reached.

Current Behavior

  1. User at 32% session usage, 98% weekly usage sends a message
  2. Claude Code returns: ⎿ API Error: Rate limit reached
  3. Usage dashboard shows limits not at 100%
  4. User is confused - what limit? Why now?

Root Cause

There are two types of rate limits, but only one is visible:

| Limit Type | Visible in Dashboard? | What it controls |
|------------|----------------------|------------------|
| Usage limits (weekly/session) | ✅ Yes | Total tokens/requests allowed |
| Throughput limits (requests/min) | ❌ No | How fast you can make requests |

The error message conflates these. Users hit the burst/throughput limit (requests per minute cap) but the message makes it sound like they've exhausted their usage quota.

Impact

  • Flow disruption: Users stop working, thinking they're out of quota
  • Support burden: Users file complaints about "hitting limits at 32%"
  • Plan confusion: "I'm paying $200/month, why am I throttled?"
  • No actionable guidance: Message doesn't explain the fix (wait 60s vs stop for the week)

Proposed Solutions

Option 1: Distinguish error messages

Current:  API Error: Rate limit reached
Better:   Rate limit: Too many requests per minute. Retry in 60s.
vs
Better:   Usage limit: Weekly quota exhausted. Resets Sun 5:59 PM.

Option 2: Show throughput limits in dashboard

Add a "Requests/min" meter to the Usage page so users can see both types of limits.

Option 3: Auto-retry with backoff

When Claude Code hits throughput limits, automatically retry after 60s instead of surfacing the error.

Reproduction

  1. Send several messages in quick succession on Opus (tool-heavy tasks)
  2. Observe API Error: Rate limit reached despite dashboard showing <100% usage
  3. Wait 60 seconds, retry → works fine

Environment

  • Plan: Pro Max ($200/month)
  • Model: Opus 4.6
  • Usage at time of error: 32% session, 98% weekly
  • Platform: macOS, Claude Code CLI v2.1.42

User Quote

"I pay $200 pro max 20% extra plan. Now this is not fair. It's really bugging my workflow. I understand if I reached usage 100% yes you hit a usage limit but I'm not using any API keys here why I'm receiving this API error rate limit reached that needs to be fixed."

Expected Outcome

Error messages should be specific and actionable:

  • Tell users which limit they hit (usage vs throughput)
  • Provide clear next steps (wait vs upgrade vs use Sonnet)
  • Show all relevant limits in the dashboard

View original on GitHub ↗

31 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/22876
  2. https://github.com/anthropics/claude-code/issues/23030
  3. https://github.com/anthropics/claude-code/issues/25733

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

lmee · 5 months ago

I went through "Rate limit errors show 'API Error' without distinguishing usage vs throughput limits" plus the discussion thread and mapped the failing path.

Problem I see: Users on paid plans (including Pro Max $200/month) are encountering API Error: Rate limit reached messages when their usage dashboard shows they haven't hit their limits. This creates confusion and disrupts workflow because the error message doesn't clarify what limit was reached.
Root-cause hypothesis: an auth/session state mismatch across validation steps.
First patch plan: reproduce the flow with deterministic steps, inspect auth/session state transitions, patch validation around the wrong-code path, and add regression coverage for happy and failure flows.
If you want this path, I can share deterministic repro notes up front and then submit the minimal fix.

joeydangelo · 4 months ago

I am also hitting "API Error: Rate limit reached" and my usage dashboard is way below limits.

iamkingsleyf · 4 months ago

I AM HAVING THIS ISSUE ON VSCODE EVEN THOUGH I USE MY OAUTH CONNECTION

SirBrenton · 4 months ago

This looks less like a “mystery limit” and more like a taxonomy gap.

There are at least two distinct limiters here:

  • Usage/quota (weekly/session) → stop until reset
  • Throughput/burst (requests/min, concurrency) → wait + retry-after/backoff

Both currently surface as “API Error: Rate limit reached,” which makes it impossible for users to take the correct next step.

To make this actionable, a tiny redacted log from 1–3 failures would help clarify which limiter is firing. No prompts/content needed — just:

  • CLI version + timestamp
  • HTTP status (e.g. 429) + error code/class
  • Any retry-after or x-ratelimit-* headers (if present)
  • Whether this was streaming
  • Rough request cadence around the failure (e.g. “5 messages in 20s”)

If it’s throughput, the fix path is clear:

  • Distinguish the error message (“Too many requests per minute. Retry in Xs.”)
  • Optionally auto-retry with bounded max-elapsed + jitter
  • (Later) expose a simple throughput indicator in the dashboard

If it’s usage exhaustion, the UX should clearly say so.

Happy to help distill this into a minimal repro/runbook if useful.

arsirantala · 4 months ago

Getting this issue as well - but only if I choose a model which has 1 mil context window like opus 4.6.

Also for me it doesn't matter if I use vscode claude code extension or iPhone Claude native app - getting the same error anyways ; and my usage is way below limits. My claude subscription is Max plan.

smarth-tech · 4 months ago

This confusion between throughput limits and usage quota limits is one of the most frustrating parts of the Claude API experience. The error message is identical for two completely different situations that require completely different responses — wait 60 seconds vs. stop for the week.
The underlying data to distinguish these actually exists in the API response headers (anthropic-ratelimit-requests-remaining, anthropic-ratelimit-tokens-remaining, etc.), but Claude Code doesn't surface it clearly when things go wrong.

I built an open-source proxy called ClaudeTrack that reads these rate limit headers from every API response and gives you real-time visibility into exactly where you stand — requests remaining, tokens remaining, and which one you're closer to exhausting.

It also predicts when you're likely to hit a limit based on your consumption pattern, so you get a warning at 75% and 90% before you see the error. You can see the live status on the dashboard, no more guessing.
It's self-hosted, MIT licensed, and takes about 2 minutes to set up with Docker. Doesn't solve the Claude Code CLI error message itself, but it gives you a separate source of truth for your rate limit status.

SirBrenton · 4 months ago

+1 — ClaudeTrack looks like a solid “surface the headers” workaround. That’s also the point: the data to disambiguate quota vs throughput already exists, but Claude Code collapses it into one message.

If someone can paste one redacted failure (HTTP status + retry-after and anthropic-ratelimit-* headers, plus whether it was streaming), I can classify which limiter is firing and propose a minimal CLI patch that prints: (a) limiter type, (b) “wait Xs” vs “stop until reset,” and (c) the relevant remaining counters.

Happy to open a PR if maintainers are open to it.

amatiasq · 4 months ago

+1, I contacted support through different channels and they all replied with the same generic description of the pricing, which makes the whole situation much more frustrating.

I already pay the 100€/month subscription and blocked me after 10 minutes of use when I have barely used it in the last 7 days. This is not normal.

amatiasq · 3 months ago

This is the first time I use Claude since my previous message.
What is going on?

<img width="587" height="166" alt="Image" src="https://github.com/user-attachments/assets/f3a7d707-05b5-4d50-a27f-509db1c1186e" />

fgrosswig · 3 months ago

same ... Claude Max 5 and get Rate limits - subscriptions between ios seems also a problem ...

amatiasq · 3 months ago

Another week and the issue remains.
Worth mentioning it only happens when using Opus

<img width="511" height="332" alt="Image" src="https://github.com/user-attachments/assets/bbc5af85-39f7-4647-9523-be8d05ba3e83" />

fgrosswig · 3 months ago

I had to recreate a new session — the old one can no longer be used. But here is the truth: Claude loses all style and depth from previous sessions unless you build a robust memory and structured documentation from Claude itself. This is simply annoying, as you have to re-teach Claude again at the cost of token credits. I don't know whether this is intentional — to drain users' capacity consumption — or simply a misconception on the user's side.

fgrosswig · 3 months ago

<img width="678" height="577" alt="Image" src="https://github.com/user-attachments/assets/b81defbb-4816-4364-a8d0-7abfad90622d" />

its totally annyoing

SirBrenton · 3 months ago

The header data @smarth-tech mentioned (anthropic-ratelimit-requests-remaining,
anthropic-ratelimit-tokens-remaining) is exactly what's needed to make
this actionable at the CLI level.

ClaudeTrack reading those headers is the right layer — if the classifier
knew which bucket fired, the CLI copy writes itself:

  • Throughput: "Too many requests per minute. Retry in Xs."
  • Quota: "Weekly limit reached. Resets [time]."

For anyone hitting this: if you can capture the full response headers
from a failure, paste them here and I can classify which limiter fired
and what the correct next step is. The data is already there — it's
just not being surfaced.

— tracking these patterns at github.com/SirBrenton/pitstop-truth

filipe-pieruccetti · 3 months ago

<img width="843" height="924" alt="Image" src="https://github.com/user-attachments/assets/6adfd2df-95f2-4ecd-9822-03729c8351db" />

<img width="2190" height="483" alt="Image" src="https://github.com/user-attachments/assets/30666775-fa69-4ae6-a027-2b3a33dd0b9f" />

I received the API rate limit reached message, I went to bed, and in the next day, even though the usage limits are apparently clear I can't do anything and the error messages persists.

SirBrenton · 3 months ago

@filipe-pieruccetti, those screenshots are useful. Session at 0% and weekly at 11% rules out quota exhaustion, which means something else is firing — likely a throughput or context-tier limit that doesn't show in the dashboard.

If you can capture the response headers from one of those failures (the anthropic-ratelimit-* headers and any retry-after value), I can tell you exactly which limiter fired and whether waiting will actually help.

filipe-pieruccetti · 3 months ago

Captured the headers. The culprit is anthropic-ratelimit-unified-overage-status: rejected with overage-disabled-reason: org_level_disabled. This means when the 5h window fills, there's no fallback — it hard-blocks instead. The error message says "rate limit reached" with no indication it's a 5-hour rolling window or that waiting ~a few hours will fix it. Dashboard doesn't expose the 5h window utilization either, only session/weekly.

SirBrenton · 3 months ago

@filipe-pieruccetti, that header is the signal.

anthropic-ratelimit-unified-overage-status: rejected with overage-disabled-reason: org_level_disabled points to a different limiter than the usual throughput throttle.

This is a rolling-window exhaustion case (looks like a ~5h window) with no overage fallback allowed, so it hard-blocks until the window resets — regardless of what the session/weekly dashboard shows.

That’s why this feels confusing: it surfaces as the same “rate limit reached” message, but the correct action here isn’t short backoff — it’s effectively wait for the window to clear.

So there are at least three distinct cases getting collapsed into one message right now:

  • short-term throughput → wait 60s + retry
  • rolling-window / policy-gated exhaustion (this case) → stop,

wait for window reset (~4h)

  • quota exhaustion → stop until weekly reset

The error doesn't tell you which one you hit, so people apply the wrong fix.

If you can share the full header block redacted, I can turn this into a clean classification note — this is exactly the primary evidence that's missing from the current error story.

filipe-pieruccetti · 3 months ago

"These headers were captured after the window reset (successful request). During the block, the dashboard showed 0% session and 11% weekly. The overage-disabled flag was present in the success headers too — I didn't capture the failure headers directly, but this confirms the limiter type."

"anthropic-ratelimit-unified-status": "allowed",
"anthropic-ratelimit-unified-5h-status": "allowed",
"anthropic-ratelimit-unified-5h-reset": "1774908000",
"anthropic-ratelimit-unified-5h-utilization": "0.35",
"anthropic-ratelimit-unified-7d-status": "allowed",
"anthropic-ratelimit-unified-7d-reset": "1775440800",
"anthropic-ratelimit-unified-7d-utilization": "0.13",
"anthropic-ratelimit-unified-representative-claim": "five_hour",
"anthropic-ratelimit-unified-fallback-percentage": "0.5",
"anthropic-ratelimit-unified-reset": "1774908000",
"anthropic-ratelimit-unified-overage-status": "rejected",
"anthropic-ratelimit-unified-overage-disabled-reason": "org_level_disabled"

filipe-pieruccetti · 3 months ago

when unified-5h-utilization was at or near 1.0 and unified-status was "blocked" instead of "allowed". That's the smoking gun header block that shows all three fields together: window full + overage rejected + hard block.

fgrosswig · 3 months ago

<img width="711" height="746" alt="Image" src="https://github.com/user-attachments/assets/362c792c-5982-4c29-afd3-a6f8ee1ddc6c" />

this is a bummer ! paying additional credits and still get cut off

<img width="1357" height="121" alt="Image" src="https://github.com/user-attachments/assets/bf62d7d3-4e82-40d7-bba1-9ac9f90e1038" />

and after a few minutes doing nothing this went to the top

<img width="702" height="232" alt="Image" src="https://github.com/user-attachments/assets/9b9a753a-7ad9-446d-a7b8-ce211dbcd2ac" />

WOW ! this is unacceptable

bibourokushi · 3 months ago

体験:6分50秒の無応答ハング、原因特定手段なし

環境:

  • プラン: Pro ($20/month)
  • プラットフォーム: Claude Code CLI(WSL/Ubuntu on Windows 11)
  • 作業内容: VLIW/SIMDカーネルコードの最適化に関する議論

発生した事象

  1. VLIW/SIMDカーネルコード最適化の作業セッションを開始
  2. 数往復のやり取り(コード片の交換、最適化方針の議論)の後、CLIが 6分50秒間、一切の出力なしに入力待ちなる 2 会発生。
  3. エラーメッセージなし、プログレス表示なし、リトライなし。
  4. 一回目は、割り込んで、状況を問い合わせると、完了したとのこと。二回目は回答なし。

原因切り分けの試行(すべて不発)

  • /cost → "You are currently using your subscription to power your claude code usage" と表示されるのみ。サブスクリプション利用者にはトークン/レート情報が提供されない。
  • /status → 5時間リミット:34%used、Weeklyリミット:62%used

/status 上は両方のリミットに余裕があり、ハングの原因を特定する手段がなかった。調査の結果、毎分スループット制限(RPM/ITPM/OTPM)に到達したと推定されるが、これは /status に一切表示されない。

問題の構造

レート制限には少なくとも3つの独立したレイヤーがある:

  1. 5時間ローリングウィンドウの使用量制限/status で表示される
  2. 週間使用量キャップ/status で表示される
  3. 毎分スループット制限(RPM/ITPM/OTPM)ユーザーに対して完全に不可視

レイヤー3に到達した場合でも、CLIは無言でハングするだけで:

  • どの制限(RPM/ITPM/OTPM)に到達したか不明
  • /status は「問題なし」と表示し続ける

ユーザーへの切り分けコスト転嫁

現状、ユーザーは以下を自力で行う必要がある:

  • ~/.claude/ 内のJSONLファイルを手動パースしてトークン消費量を推定
  • ccusage等の外部ツールを導入
  • 場合によっては別プラットフォームでリトライして、repo fingerprint由来の制限かどうかを切り分け

これはデバッグ作業であり、$20/月であっても$200/月であっても、有料ユーザーに求めるべき作業ではない、と考える

提案

  1. /status に RPM/ITPM/OTPM の現在値と上限を表示する
  2. スループット制限到達時に、明確なエラーメッセージを表示する
  • 例:Throughput limit: ITPM exceeded. Retry in 45s.(使用量制限とは明確に区別)
  1. CLIが自動リトライするか、ユーザーに選択肢を提示する
  2. 無応答ハングを発生させない。タイムアウトでもエラーでも、何かしらのフィードバックが必要
SirBrenton · 3 months ago

@bibourokushi — this is a precise breakdown of exactly the problem. The three-layer structure you've identified (5h window, weekly cap, per-minute throughput) is the same pattern documented across multiple systems.

The silent hang is the worst case — no signal means no correct action. At minimum the CLI should surface which layer fired and whether waiting will help.

If you can capture the response headers from one of those failures, I can classify exactly which limiter fired and what the correct wait time is.

— tracking these patterns at
github.com/SirBrenton/pitstop-truth

Asobu01 · 2 months ago

I can take anthropics/claude-code#25805.
For "Rate limit errors show 'API Error' without distinguishing usage vs throughput limits", I will start by reproducing the UI/layout issue and isolating the component/state that causes it.
Target: draft PR in ~8h.
Deliverables: minimal UI fix aligned with current UX; quick before/after validation notes; PR with clear change summary.
I keep UI changes consistent and low-risk, with quick validation notes. (@Asobu01)

Asobu01 · 2 months ago

Quick follow-up on anthropics/claude-code#25805. I am still ready to start immediately and can post the first repro/checklist note before the draft PR if helpful. If you want me on this one, I can begin now. (@Asobu01)

MukundaKatta · 2 months ago

The 429 response carries anthropic-ratelimit-* headers that signal which bucket fired (requests-per-min vs tokens-per-min) plus a retry-after when present. Surfacing whichever header is at zero, with the retry-after, in the CLI message would give users a concrete next step without any API change. Right now both signals get dropped before they reach the terminal.

SirBrenton · 2 months ago

This issue has shown up in three forms so far.

1) Throughput vs quota confusion. Same error, different causes.
2) Rolling window overage. Needed a long wait, treated like a short retry.
3) Current state:

Retry-After is present.
Auth buckets are scoped.
CLI parses headers.

Install still fails.

So the problem is no longer missing signals. The signals are there, but they are not driving a decision in the CLI.

Reference:
https://github.com/SirBrenton/pitstop-truth/blob/main/receipts/2026/05/PT-2026-05-05-github-anthropics-claude-code-25805-429-signal-not-actionable/receipt.json

m13v · 2 months ago

OP's split is right but there's a third axis: server quota (the object claude.ai/settings/usage renders, weekly + 5h rolling counters), throughput cap (RPM, not exposed anywhere), and local token tallies (what ccusage parses out of ~/.claude/projects/.jsonl). Local tallies can't see the server quota at all, and the server endpoint doesn't expose RPM. So 32% session + 98% weekly + RPM-throttled all collapse into the same 'Rate limit reached' string. Surfacing the X-RateLimit- headers on the rejected response would fix most of this without touching the dashboard at all.

SirBrenton · 2 months ago

Wrote up the three-receipt arc for anyone following this thread:

https://blog.pitstop.dev/i-tracked-this-bug-across-three-months-the-signals-were-there-the-whole-time/

Three months, three distinct failure shapes, one issue.

github-actions[bot] · 1 month ago

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