Repository navigation
Fail over to next account on 429 instead of blocking - #13
Closed
brendandebeasi wants to merge 1 commit into
Closed
brendandebeasi wants to merge 1 commit into
brendandebeasi wants to merge 1 commit into
Conversation
A 429 (quota exhaustion or rate limit) was treated as transient: the proxy slept for the full retry-after and retried the same account, never marking it unavailable. For real quota exhaustion retry-after can be hours, so the client connection hung until Claude Code gave up with an "API overloaded" error; only a restart (which re-probes every account) routed around the dead account. Now a 429 marks the account rate-limited for the retry-after window and immediately fails over to the next available account. When every account is throttled the client gets a 429 with a correct retry-after to back off on, instead of a hung connection.
This was referenced May 28, 2026
daniel-rudaev
added a commit
to D1DX/teamclaude
that referenced
this pull request
May 30, 2026
- 429: mark account rate-limited and fail over to the next available account instead of sleeping retry-after on a dead account (PR KarpelesLab#13). - 529: hold the client and retry with exponential backoff (cap 60s/wait) for ~1h, then return 529. - OAuth-beta: keep oauth-2025-04-20 in anthropic-beta on OAuth requests to avoid spurious 401s (PR KarpelesLab#3). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MagicalTux
added a commit
that referenced
this pull request
Jun 18, 2026
One Anthropic account (email/accountUuid) can hold multiple subscriptions across different organizations — e.g. a corporate Pro org and a personal Max org. The old identity model keyed only on accountUuid (with name as fallback), so adding the second org overwrote the first (#6) and --name couldn't help because the UUID check won (#7). Identity is now (accountUuid + organization). Re-implemented and reviewed against master rather than cherry-picking the closed fork PRs (#15/#17). - src/identity.js (new): orgKey / sameIdentity / matchAccounts / emailOf, the single source of truth for identity and lookups. sameIdentity treats an unknown org on either side as a match so a freshly-profiled login backfills a legacy entry instead of duplicating it. - fetchProfile: extract organization.uuid; accounts persist orgUuid/orgName. - All dedup/sync/find match sites switched to sameIdentity; syncAccountsFromDisk uses a greedy 1:1 claim so multiple same-person/different-org entries pair correctly. accounts command dedups by (accountUuid, org) and backfills org. - Name disambiguation: one org -> "email"; multiple -> "email (Org)", renaming the existing collider too. Names stay unique (they are the user-facing key). - Org-aware remove + api: resolve by name or email, --org <name|uuid> to disambiguate; lists candidates when ambiguous. - Per-account rotation priority: `priority` field (lower = preferred, default 0) as the primary sort key in _selectNext with the existing weekly heuristic as tiebreaker; new `teamclaude priority` command (--first/--last); session-reset switching won't demote to a worse priority. - Tests: identity/matchAccounts/emailOf and priority rotation (22 passing). - Docs: README, config.example.json, help text. Out of scope (future PRs from the #18 stack): #14 headless/reload API/prober, #16 usage-endpoint quota. #13 (429 account-failover) intentionally not taken — the throttle is IP-based, so the merged #25 back-off is the correct behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When an account returns a 429 (quota exhaustion or rate limit), the proxy treated it as transient: it slept for the full
retry-afterand retried the same account, never marking it unavailable. For genuine quota exhaustionretry-aftercan be hours, so the client connection hangs until the client (e.g. Claude Code) gives up with an "API overloaded" error. The only workaround was restarting the proxy, which re-probes every account and routes around the dead one.This changes the 429 path to:
retry-afterwindow (markRateLimited), sogetActiveAccount()skips it.retry-afterto back off on, instead of holding the connection open.Test plan
retry-afterimmediately (no long hang).retry-after.