Skip to content

fix(claude): put the rate-limit reset in 429 error messages - #7015

Open
ThallesP wants to merge 4 commits into
router-for-me:devfrom
ThallesP:fix/claude-429-reset-in-message
Open

ThallesP wants to merge 4 commits into
router-for-me:devfrom
ThallesP:fix/claude-429-reset-in-message

Conversation

@ThallesP

@ThallesP ThallesP commented Oct 26, 2026 •

Copy link
Copy Markdown

Note

From Claude (agent)

Claude Code drops Retry-After and reports only the error message, so a client driving Claude Code through the proxy can't tell when a 429 clears. A model cooldown already computes reset_time, and an upstream Claude 429 carries the reset parsed from the rate-limit headers, but the Claude-format error keeps neither.

toClaudeError now appends (reset after <duration>) to 429 messages when the error knows its reset: the pool cooldown's Retry-After, or the upstream error's RetryAfter(). The JSON response and the SSE event: error both go through it. Other statuses, and 429s without a reset, are unchanged.

Once every credential is cooling down, Claude Code now shows:

API Error: Request rejected (429) · All credentials for model claude-opus-4-6 are cooling down (last error: rate_limit_error: This request would exceed your account's rate limit. Please try again later.) (reset after 2h34m5s)

T3 Code reads this suffix to schedule an automatic resume at the reset: pingdotgg/t3code#25520

Tests: TestClaudeErrorPutsRateLimitResetInMessage covers the pool cooldown, an upstream limit with RetryAfter(), and a 429 without a reset; the first two fail without the change. go test ./sdk/api/handlers/claude/ passes and ./cmd/server builds. The same patch on v8.0.3 is running locally behind Claude Code and returns the suffix on cooldown 429s.

Claude Code drops the Retry-After header and reports only the error
message, so a client running through the proxy never learns when the
cooldown ends. Append "(reset after <duration>)" to Claude-format 429
messages, from the pool cooldown or the upstream rate-limit reset.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-26T15:12:44.808694Z 5c5402d Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cd9785815f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Claude Fast 429s are written as the raw upstream body and skipped the
reset suffix. Append it to that body's error.message too.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@ThallesP

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2c1f3b9c59

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

A request interceptor can end a request with a Claude-format 429 whose
reset lives only in its Retry-After header. Fall back to that header
when the error carries no reset.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@ThallesP

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f95b1248d6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Reading Retry-After from a direct response's raw headers also picked up
upstream Claude Fast values the rate-limit parser rejects. A terminating
interceptor already writes its whole response, so drop the fallback and
take the reset only from the error.

This reverts commit f95b124.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@ThallesP

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: 5c5402ddf6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@EhsanulHaqueSiam

Copy link
Copy Markdown

Note

🤖 Agent responding on behalf of EhsanulHaqueSiam

This is still needed on v8.0.56, but the branch no longer builds on main: the direct-response branch uses gjson/sjson, which main replaced with ojson. GitHub shows it as mergeable because there is no text conflict, but go build ./sdk/api/handlers/claude/ on main + this diff fails:

code_handlers.go:616:18: undefined: gjson
code_handlers.go:617:27: undefined: sjson

The port is two lines:

if message := ojson.GetBytesNoCopy(body, "error.message"); message.Type == ojson.String {
	if updated, errSet := ojson.SetBytes(body, "error.message", fmt.Sprintf("%s (reset after %s)", message.String(), resetIn)); errSet == nil {

and gjson.GetBytes → ojson.GetBytesNoCopy in TestWriteClaudeDirectErrorPutsRateLimitResetInMessage.

With that port on v8.0.56, go test ./sdk/api/handlers/claude/ ./sdk/cliproxy/auth/ passes, and an end-to-end run shows the fix works:

  • Setup: one api-keys.claude key pointed at a stub upstream that answers 429 with Retry-After: 3600, and Claude Code 2.1.318 using ANTHROPIC_AUTH_TOKEN, as in the common hub setup.
  • Unpatched v8.0.56: Claude Code fails at the first request (it doesn't retry a long Retry-After) and reports only API Error: Request rejected (429) · All credentials for model … are cooling down via provider claude. The header is dropped, so clients get no reset time.
  • Patched, first request (upstream 429): … are cooling down via provider claude (reset after 1h0m5s).
  • Patched, second request (pool cooldown, answered locally with no upstream call): … (last error: …) (reset after 1h0m5s).

T3 Code already reads that suffix from a direct 429 (pingdotgg/t3code#25438, in current nightlies), which turns both results into a 3605 s reset. That makes auto-resume and snooze work for proxied Claude threads with no T3 change. Without this patch, T3 users report the missing reset in pingdotgg/t3code#26574.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants