[IMPROVEMENT] Claude Code should surface retry state and handle 429s gracefully instead of silent spinner freeze

Resolved 💬 7 comments Opened May 8, 2026 by Manuelreyesbravo Closed May 11, 2026

[IMPROVEMENT] Claude Code should surface retry state and handle 429s gracefully instead of silent spinner freeze

Summary

When Claude Code hits a rate-limited response (x-should-retry: true), it retries silently up to 6 times over ~23 seconds before surfacing a generic error — leaving the user watching an indistinguishable spinner the entire time. This is a pure client-side UX and reliability fix that doesn't require any backend changes.

This was uncovered while investigating #53922. @cnighswonger confirmed the retry sequence with an HTTP-level capture (88 consecutive 429s logged).

---

Current behavior

  1. Session hits a 429 with x-should-retry: true
  2. Claude Code retries silently: 0.86s → 1.4s → 2.2s → 3.8s → 6.9s → 8.4s (~23.5s total)
  3. On final failure: "Server is temporarily limiting requests · Rate limited"
  4. Session appears frozen with no distinction from a normal thinking spinner

The user has no idea whether to wait, cancel, or restart. In practice, most users restart — creating a new session that immediately competes with existing ones and worsens the concurrency pressure.

---

What Claude Code can fix on its own

1. Show retry state in the UI

Once x-should-retry: true is received, replace the spinner with something like:

⏳ Rate-limited — retrying (2/6, next in 2.2s)

This single change eliminates the "is it frozen or thinking?" confusion and stops users from manually restarting sessions unnecessarily.

2. Client-side request queue instead of per-request retry

Instead of each session independently retrying the same 429 window, a small shared queue with (base_delay × 2^attempt) + jitter would:

  • Prevent multiple sessions from hammering simultaneously
  • Keep sessions alive rather than exhausting their budget and dying
  • Surface queue position in the UI: "Queued behind 2 other requests"

3. Persist session state through a rate-limit window

Currently, once retry budget is exhausted, the session is effectively dead. Claude Code should distinguish "rate-limited" from "error" — preserving the session context and offering to resume when the window clears, rather than requiring a full restart.

---

Evidence

From @cnighswonger's HTTP capture (referenced in #53922):

  • Retry signal confirmed as x-should-retry: true (not Retry-After)
  • 88 consecutive 429s captured in a 15-minute window
  • p95 latency 882ms — gateway-level rejection, backend never involved
  • Burst triggered by multiple agents resuming simultaneously (wake-from-idle pattern)

All three improvements above are implementable without any API or backend changes — purely in the Claude Code client.

---

Related

  • #53922 — root cause (server-side concurrency cap)
  • #46037, #38335, #41788 — same symptom reported by other users

---

@cnighswonger — given your HTTP-level captures, you likely have the clearest view of the retry sequence from the wire. Would love your input here, especially on whether the x-should-retry signal carries enough timing information for the client to implement smarter backoff, or if Fix #6 from #53922 (restoring anthropic-ratelimit-* headers on 429s) is a prerequisite for that.

View original on GitHub ↗

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