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
- Configure two Codex pool accounts and bind a parent thread to account A.
- Keep account B eligible.
- A displayed quota may reach
100%; do not pause or move the existing thread on that value alone.
- Make A return an actual pre-response upstream
429 or 402.
- 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
Client or integration
Codex App
Area
Proxy and routing
Summary
/v1/responses/compactdoes 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-response429or402, the compact path records the outcome and returns it directly. Codex then retries the remote compact task outside the logical request and can end withexceeded retry limit, although another pool account is eligible.Expected behavior:
100%usage snapshot alone must not move an existing thread or compact request.429/402, record the failed account and try exactly one eligible alternate in the same compact request.Retry-After, and cancellation.Relevant source:
src/server/responses/compact.ts:handleResponsesCompact()and compact pool outcome recording.src/server/responses/core.ts: existing regular-Responses bounded429/402alternate flow.src/codex/auth-context.ts:excludeAccountIdresolution.src/codex/routing.ts: alternate selection and upstream outcome state.Required regression coverage in
tests/responses-compaction-routing.test.ts:429and402alternate success, no-alternate preservation, alternate rejection capped at two sends, abort before retry, correct alternate credentials, and proof that100%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
100%; do not pause or move the existing thread on that value alone.429or402./v1/responses/compactwith the samex-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 ondevat075c2f34c060d068ed56985e76924a9f23aca39dwhen 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
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