Skip to content

Account Pooler: a transient 5xx, 529 or connection error moves a pinned Claude session to another account for good #6990

Closed

Description

@MGrin

Summary

When the account a conversation is pinned to returns HTTP 408, 500, 502, 503, 504 or 529, or the connection fails, the Account Pooler retries the request on the next account at once. If that account answers, the pool rebinds the session pin to it permanently. The conversation never returns to its first account, even after that account recovers a second later. Prompt caches belong to one account, so the move rewrites the whole cached context on the new account at the cache-write price, for a failure that was not about the account. I expected the pool to retry the pinned account briefly first and, if it still fails over, to keep the pin, as it already does for a model-family limit (familyDetour).

Versions and environment

  • bb 0.48.1 (bb --version), installed from npm (bb-app), and main at dbb247c60f46494579adb40b80efa7c8a861b35c.
  • Linux 7.0.0 (Azure), Node v22.23.4.
  • Provider: Claude Code through the Account Pooler, two or more Claude accounts in the pool.

Steps to reproduce

The failure is transient upstream, so the faithful repro is a test at the exact code path. With two API-key accounts in plugins/account-pool/src/server.test.ts (affinityFixture):

  1. Send a Claude request with session warm. It is served by sk-first, and warm is pinned to sk-first.
  2. Make sk-first answer the next request with HTTP 503 (or throw from fetch to simulate ETIMEDOUT).
  3. Send warm again. It is served by sk-second.
  4. Let sk-first recover. Send warm again.

The existing test keeps %s sessions and the pool cursor on the third account after two failures asserts this behaviour on main: after one outage, warm stays on the fallback account.

Expected vs actual

Actual (upstream attempts, main): ["sk-first", "sk-first", "sk-second", "sk-second"]. Step 4 goes to sk-second; the pin moved in step 3 and never returns.

Expected: step 3 retries sk-first with a short backoff before it fails over, and step 4 goes back to sk-first: ["sk-first", "sk-first", "sk-first", "sk-first", "sk-second", "sk-first"] when the outage outlasts the retries.

Evidence

  • Failover after a transient status or a connection error: hub.ts#L576-L597, hub.ts#L650-L736. Each breaks out to the next account with no same-account retry.
  • The rebind: hub.ts#L999-L1004. attempted.has(bound.account.id) rebinds whenever the pinned account was tried in this request, whatever the reason. Only familyDetour is exempt.
  • Observed on 0.48.1 pool logs: ETIMEDOUT bursts of 3 to 5 requests. Each burst can move every active conversation off its account. The extra cache writes were not measured: the pool records no per-request token usage.

What I ruled out

Suggested priority and effort

Hits every multi-account Claude pool during upstream overloads or network blips. No data loss, but each move costs a full cache rewrite on the fallback account. Small, plugin-local change.

AGENT GENERATED

Activity

  1. added theissue type on Nov 4, 2026
  2. added
    providersCross-provider bridges, models, login
    confirmed-reproBug reproduced again from a clean trusted checkout; see linked report
    on Nov 4, 2026
  3. bb-slop-cop commented on Nov 4, 2026

    @bb-slop-cop
    Contributor

    🚨 SLOP COP 🚨 · new-issue-autopilot

    • Classification: Bug · Medium priority · Low effort.
    • Labels: providers, provider-claude-code, confirmed-repro.
    • Reproduction report: REPRODUCED · high confidence. All six transient HTTP statuses and a simulated connection failure reproduce in two clean checkouts of trusted main (8d131a26); existing routing controls pass.
    • Root cause: the successful fallback overwrites the session binding because routing tracks attempted accounts without distinguishing transient failures from account-specific refusals. The pinned account receives no same-account retry. Recovery still routes to the fallback; cache charges were not measured.
    • No new PR: open PR #6991 already links to this issue, so another fix PR would duplicate it. Its branch was not executed.

    AGENT GENERATED

  4. added a commit that references this issue on Nov 5, 2026
    e6edc63
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-reproBug reproduced again from a clean trusted checkout; see linked reportprovider-claude-codeBuilt-in plugin: provider-claude-codeprovidersCross-provider bridges, models, login

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions