Repository navigation
fix(anthropic): fail over on proven pre-output account 403 refusals - #6347
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
✅ Deterministic PR hygiene checks passed. |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Repository: lidge-jun/opencodex/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (26)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Maintainer integration into |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b94839264e
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| allowAccountRefusal?: boolean; | ||
| }, | ||
| ): Promise<string | null> { | ||
| if (options.signal?.aborted || isNonReplayableResponse(response)) return null; |
There was a problem hiding this comment.
Preserve 429 cooldown recording after cancellation
When an upstream 429 has already resolved but the client aborts before this helper runs, this early return skips both rotation and recordAnthropicAccountRefusal. Previously the 429 path recorded the sender's cooldown even when no retry could be made, so the next request now may immediately select an account already proven rate-limited. Keep cancellation from authorizing a resend, but still record a replayable 429—for example, by applying the abort guard only to 403 body classification and passing canRetry: false for an aborted 429.
AGENTS.md reference: src/AGENTS.md:L17-L19
Useful? React with 👍 / 👎.
Summary
The Anthropic OAuth account pool rotated to the next account only on HTTP 429. When one pooled account's Claude subscription had expired, the upstream answered 403 before any output, and the request failed even though other accounts in the pool were healthy.
A pre-output 403 now fails over to the next account only when it proves an account-level refusal. That requires complete, bounded JSON, a recognized error type, and exact account-entitlement or billing wording, and the bearer and credential generation that actually sent the request must still match. A recognized refusal clears affinity and cools that account, using
Retry-Afteror ten minutes by default, then the request moves to the next account under the existing rotation cap and send budget. Generic permission, policy, malformed, overridden-credential and stale-credential 403s stay terminal. No 403 failover happens after output has begun. Main dispatch, continuations, sidecars and web search follow the same rule. Docs and translations that described 429-only rotation are updated.Closes #6340
Verification
bun test tests/adapters/anthropic/anthropic-quota-dispatch.test.ts: red 18 pass / 9 fail before the fix, green 40 pass / 0 fail after. It covers entitlement recovery, negative classifications, credential replacement, header overrides, exhausted pools, strict routes, continuations and sidecars.dev: the changed tests plus test-layout and file-size guards pass (67 pass / 0 fail);bun x tsc --noEmit,structure:checkandprivacy:scanpass.devtip before release.Checklist