Repository navigation
fix(anthropic): eject an OAuth account whose access token was revoked - #6832
Conversation
📝 WalkthroughWalkthroughThe change adds recovery for Anthropic OAuth accounts that return an exact revoked-token 401 before output begins. It marks the sending account for reauthentication and supports eligible retries across native Messages, Responses, continuation, search, and image paths. Tests and documentation cover the recovery conditions and limits. ChangesAnthropic OAuth account recovery
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Bug fix · Severity of issue fixed: Medium Sequence Diagram(s)sequenceDiagram
participant Client as Claude Code
participant Messages as handleNativeMessages
participant Recovery as rotateAnthropicAccountOnResponseForInstance
participant Store as markAccountNeedsReauthIfGeneration
participant Binding as resolveNativeOAuthBindingForInstance
Client->>Messages: Send request
Messages->>Recovery: Process exact revoked-token 401
Recovery->>Store: Mark sending account for reauthentication
Recovery->>Recovery: Clear affinity and select eligible alternate
Recovery-->>Messages: Return recovery candidate
Messages->>Binding: Check candidate selection and model route
Binding-->>Messages: Return eligible account binding
Messages-->>Client: Retry request or return original 401
Suggested reviewers: Merge Risk: ⚪ Minimal · up to The changed recovery remains gated before output, with no established issue requiring a fix before merge. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)✅ Passed checks (4 passed)Full details: Docstring CoverageExplanation Docstring coverage is 31.71% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 41 functions across 16 files. (16 skipped: 16 unsupported.)
✨ Finishing Touches 💡 1📝 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 |
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. |
Account recovery handled only 429 and 403, so an exact revoked-token 401 was returned to the client while session affinity kept pinning the same account. Before any output, classify that exact envelope (bounded, fatal UTF-8, no error code), mark the sending account needsReauth under a credential-generation and send-ownership fence, clear its affinities, and allow an eligible same-pool account to take over within existing send limits. Covers native Messages (including pool-off admission order), translated dispatch and continuation, and the web-search and image sidecars. Other 401s and anything after output keep their existing behavior. Closes #6749
f096fa7 to
f84a73f
Compare
There was a problem hiding this comment.
🔇 Additional comments (32)
src/oauth/anthropic-account-refusal.ts (1)
110-131: LGTM!src/oauth/anthropic-routing.ts (1)
707-707: LGTM!src/oauth/anthropic-send-ownership.ts (1)
35-36: LGTM!src/oauth/store.ts (1)
1511-1511: LGTM!tests/adapters/anthropic/anthropic-revoked-token.test.ts (1)
1-234: LGTM!tests/adapters/anthropic/anthropic-revoked-token-boundaries.test.ts (1)
1-110: LGTM!src/server/messages-native-oauth.ts (1)
142-155: LGTM!src/server/messages-native.ts (1)
516-516: LGTM!Also applies to: 688-688, 706-706
src/server/responses/adapter-continuation.ts (1)
404-404: LGTM!Also applies to: 431-431
src/server/responses/adapter-dispatch.ts (1)
1100-1100: LGTM!Also applies to: 1125-1125
src/server/responses/sidecar-execution.ts (1)
207-207: LGTM!Also applies to: 371-371
src/images/loop.ts (1)
707-707: LGTM!src/web-search/loop.ts (1)
580-581: LGTM!tests/claude-integration/messages-revoked-token.test.ts (1)
1-215: LGTM!tests/adapters/anthropic/anthropic-revoked-token-continuation.test.ts (1)
1-127: LGTM!tests/adapters/anthropic/anthropic-revoked-token-sidecars.test.ts (1)
1-139: LGTM!docs-site/src/content/docs/guides/claude-code.md (1)
84-89: LGTM!docs-site/src/content/docs/ja/guides/claude-code.md (1)
634-634: LGTM!docs-site/src/content/docs/ko/guides/claude-code.md (1)
697-697: LGTM!docs-site/src/content/docs/ru/guides/claude-code.md (1)
669-669: LGTM!docs-site/src/content/docs/tr/guides/claude-code.md (1)
891-891: LGTM!docs-site/src/content/docs/zh-cn/guides/claude-code.md (1)
600-600: LGTM!docs-site/src/content/docs/zh-tw/guides/claude-code.md (1)
676-676: LGTM!structure/data-planes/images.md (1)
25-26: LGTM!structure/data-planes/inbound-compat.md (1)
519-520: LGTM!structure/providers-and-adapters.md (1)
10-10: LGTM!structure/providers/anthropic-account-pool.md (1)
301-322: LGTM!structure/transports/inventory.md (1)
46-46: LGTM!structure/transports/responses-failover.md (1)
545-545: LGTM!scripts/test-layout/layout.json (1)
7-11: LGTM!tests/fixtures/test-layout-expected.json (1)
4-8: LGTM!docs-site/src/content/docs/fr/guides/claude-code.md-779-779 (1)
779-779: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.Wrap code identifiers in backticks to fix the false typographic warning.
On Line 779, the identifiers
authentication_erroranderror.codeare plain text. LanguageTool readserror.codeas a sentence break and asks for a space after the period. The English source uses backtick formatting for these identifiers. Add backticks here so the French page matches the English page and the period stays part of the identifier.Proposed fix
-Uniquement avant toute sortie : Un HTTP 401 authentication_error (sans error.code) portant +Uniquement avant toute sortie : un HTTP 401 `authentication_error` (sans `error.code`) portantThe same plain-text identifiers also appear on the ja, ko, ru, tr, zh-cn and zh-tw pages. Apply the same change there.
Source: Linters/SAST tools
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml
- Review profile: ASSERTIVE
- Plan: Advanced
- Run ID:
93dd7b0d-d15a-4a5e-9a3c-d80ffc0550fa
📒 Files selected for processing (32)
docs-site/src/content/docs/fr/guides/claude-code.mddocs-site/src/content/docs/guides/claude-code.mddocs-site/src/content/docs/ja/guides/claude-code.mddocs-site/src/content/docs/ko/guides/claude-code.mddocs-site/src/content/docs/ru/guides/claude-code.mddocs-site/src/content/docs/tr/guides/claude-code.mddocs-site/src/content/docs/zh-cn/guides/claude-code.mddocs-site/src/content/docs/zh-tw/guides/claude-code.mdscripts/test-layout/layout.jsonsrc/images/loop.tssrc/oauth/anthropic-account-refusal.tssrc/oauth/anthropic-routing.tssrc/oauth/anthropic-send-ownership.tssrc/oauth/store.tssrc/server/messages-native-oauth.tssrc/server/messages-native.tssrc/server/responses/adapter-continuation.tssrc/server/responses/adapter-dispatch.tssrc/server/responses/sidecar-execution.tssrc/web-search/loop.tsstructure/data-planes/images.mdstructure/data-planes/inbound-compat.mdstructure/providers-and-adapters.mdstructure/providers/anthropic-account-pool.mdstructure/transports/inventory.mdstructure/transports/responses-failover.mdtests/adapters/anthropic/anthropic-revoked-token-boundaries.test.tstests/adapters/anthropic/anthropic-revoked-token-continuation.test.tstests/adapters/anthropic/anthropic-revoked-token-sidecars.test.tstests/adapters/anthropic/anthropic-revoked-token.test.tstests/claude-integration/messages-revoked-token.test.tstests/fixtures/test-layout-expected.json
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review.
Summary
An Anthropic OAuth account whose access token was revoked now leaves the pool instead of looping on 401. Before this change, account recovery handled only 429 and 403. A 401 with
OAuth access token has been revoked.was returned to the client while session affinity kept pinning the same account, so affinity-bound Claude Code sessions repeated the same 401 for hours (#6749).When a response before any output is an HTTP 401 whose body is exactly
{"type":"error","error":{"type":"authentication_error","message":"OAuth access token has been revoked."}}with noerror.code(absent or null), the proxy now:needsReauthunder the store lock, only if the same credential generation and physical-send ownership are still current, so a re-login that lands in between is never overwritten;anthropicoranthropic2, never across pools) take over within the existing per-request and physical-send limits;The body is read bounded, with fatal UTF-8 decoding. Truncated, malformed, timed-out, or cancelled reads, other 401 messages, and any 401 after output has started keep their existing behavior; nothing is marked and nothing is replayed after output. The path covers native Messages (JSON and SSE, including with proactive pooling off, where the recovery candidate is now considered before ordinary admission and must still pass eligibility, selection-revision, and route checks), translated dispatch and continuation, and the web-search and image sidecars (their early gate now admits an Anthropic 401 next to 403). No account is refreshed or deleted, and no body, token, or account identifier is logged; recovery telemetry reuses the existing
oauth-401kind.Closes #6749
Verification
tests/adapters/anthropic/anthropic-revoked-token.test.ts(classifier: exact envelope, code/null, wording, truncation, fatal UTF-8, cancellation, generation fencing),tests/claude-integration/messages-revoked-token.test.ts(native JSON/SSE, both pools, pool on and off, no sibling, post-output),anthropic-revoked-token-continuation.test.ts,anthropic-revoked-token-sidecars.test.ts, andanthropic-revoked-token-boundaries.test.ts(queued-writer races: UUID, cancellation, quota epoch, remove/re-add, disabled Pool 2, post-output search). 117 pass; before the source change the first four fail 50 of 106.tests/oauth/oauth-anthropic-*): 885 pass across 33 files.messages-native,messages-native-oauth,test-layout,test-layout-tooling,file-size-ratchet,core-lab-boundary: 130 pass.bun run typecheck,bun run structure:check,bun run privacy:scan, anddocs-sitebun run build(569 pages) pass.Checklist
structure/providers/anthropic-account-pool.mdand five other owning structure docs; Claude Code guide in 8 languages)Summary by CodeRabbit