Skip to content

[Bug]: /v1/responses/compact returns pool 429/402 without same-request alternate attempt #913

Description

@luvs01

Client or integration

Codex App

Area

Proxy and routing

Summary

/v1/responses/compact does not have the bounded same-request alternate-account handling already used by regular /v1/responses.

An existing thread should remain on its affined account even when WHAM displays 100%: Codex can continue an in-progress task until upstream actually rejects it. Today, when that account returns a pre-response 429 or 402, the compact path records the outcome and returns it directly. Codex then retries the remote compact task outside the logical request and can end with exceeded retry limit, although another pool account is eligible.

Expected behavior:

  • A 100% usage snapshot alone must not move an existing thread or compact request.
  • After an actual upstream 429/402, record the failed account and try exactly one eligible alternate in the same compact request.
  • Rebuild the alternate bearer/account headers and preserve quota scope, writer generation, affinity, reset headers, Retry-After, and cancellation.
  • Cancel the first response body before the alternate send.
  • If no alternate exists, preserve the original rejection body and headers.
  • If the alternate also rejects, stop after two total sends. No recursion or reset-credit redemption.

Relevant source:

  • src/server/responses/compact.ts: handleResponsesCompact() and compact pool outcome recording.
  • src/server/responses/core.ts: existing regular-Responses bounded 429/402 alternate flow.
  • src/codex/auth-context.ts: excludeAccountId resolution.
  • src/codex/routing.ts: alternate selection and upstream outcome state.

Required regression coverage in tests/responses-compaction-routing.test.ts: 429 and 402 alternate success, no-alternate preservation, alternate rejection capped at two sends, abort before retry, correct alternate credentials, and proof that 100% without upstream rejection leaves existing affinity unchanged.

Related: #584/#585 (regular Responses parity), #815/#834 (known 100% is not unknown for new routing decisions), #657 (advisory usage vs actual rejection), and #433 (cooldown recovery).

Reproduction

  1. Configure two Codex pool accounts and bind a parent thread to account A.
  2. Keep account B eligible.
  3. A displayed quota may reach 100%; do not pause or move the existing thread on that value alone.
  4. Make A return an actual pre-response upstream 429 or 402.
  5. Send /v1/responses/compact with the same x-codex-parent-thread-id.

Current: A's rejection is returned directly and Codex can exhaust its remote compact retry budget.

Expected: A is attempted once, the real rejection authorizes one attempt on B, and B's successful compact response is returned in the same HTTP call.

Version

2.10.0; the relevant compact, routing, auth-context, and retry sources were unchanged on dev at 075c2f34c060d068ed56985e76924a9f23aca39d when checked on 2026-08-03.

Operating system

Windows 11 Pro 10.0.26200 (platform-independent routing defect).

Provider and model

OpenAI (Codex login / forward account pool); native Codex models.

Logs or error output

Error running remote compact task: exceeded retry limit, last status: 429 Too Many Requests

Screenshots and supporting files

None. Account and request identifiers are intentionally omitted.

Redacted configuration

{
  "providers": {
    "openai": {
      "adapter": "openai-responses",
      "authMode": "forward",
      "codexAccountMode": "pool"
    }
  },
  "accountPoolStrategy": "fill-first",
  "accountPoolStickyLimit": 1,
  "autoSwitchThreshold": 100,
  "upstreamFailoverThreshold": 3,
  "activeCodexAccountId": "__main__"
}

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Metadata

Metadata

Assignees

No one assigned

    Labels

    account-poolOAuth, credentials, Codex pool, quota, failover, plansbugSomething isn't workingproxyHTTP proxy, routing, reverse-proxy / management auth

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions