Client or integration
Codex App
Area
Authentication and account pool
Summary
A reset-derived Codex cooldown can remain after the account recovers early when another pool account remains eligible.
An actual upstream 429 with reset headers creates a non-persistent cooldown. The cooled account is excluded, and the current recovery probe is acquired only after routing selects that account. If another account can always serve traffic, the cooled account is never selected, so it never receives the bounded probe. A forced fresh WHAM read may show recovery, but updating quota cache does not clear the matching routing cooldown.
Persistently pausing an account at displayed 100% is not a valid workaround: OpenAI can reset earlier than the predicted timestamp, 100% can remain advisory while an in-progress task still succeeds, and pause can outlive the restriction.
Expected behavior:
- Create cooldown only after an actual upstream rejection; a WHAM
100% snapshot alone must not create cooldown, pause, or move an existing thread.
- Keep reset-derived exclusion non-persistent.
- At a bounded interval, permit one single-flight fresh quota refresh for a due reset-derived candidate even while another account serves requests.
- Fence by account identity, credential generation, quota scope, and cooldown generation.
- Clear only the matching reset-derived scope/generation when a complete fresh authoritative snapshot proves recovery.
- Retain cooldown on still-
100%, incomplete, stale, unavailable, unrelated-scope, or replaced-credential results.
- Do not clear explicit
Retry-After or headerless/default cooldowns through this path.
- Fail closed without delaying ordinary traffic on the healthy alternate.
Relevant source:
src/codex/routing.ts: reset-derived health, generations, scope, selection, and probe leases.
src/codex/auth-context.ts: probe admission currently occurs only after selection.
src/codex/auth-api.ts: main/pool forced refresh and existing single-flight.
src/codex/quota.ts: freshness and authoritative exhaustion.
Required tests: early recovery with another eligible account; still-exhausted/unknown/fetch-failure cases; concurrent single-flight; stale-generation rejection; main and pool accounts; shared vs Spark scope separation; explicit Retry-After untouched; all pool strategies re-include the recovered account; paused unchanged; and no cooldown/rebinding from a standalone 100% snapshot.
Related: #433 (bounded probe/cap), #590/#599 (scoped cooldowns), #584/#585 (same-request failover after real rejection), and #657/#866 (separate reset-credit semantics).
Reproduction
- Configure accounts A and B.
- Let A receive an actual upstream
429 with reset headers.
- Keep B eligible so traffic continues through B.
- Let OpenAI reset A earlier than the recorded deadline.
- Force a fresh authoritative quota read while continuing traffic through B.
Current: A's quota cache updates, but its routing cooldown remains because A is never selected for the existing probe.
Expected: one bounded refresh clears only A's matching reset-derived generation, A becomes eligible immediately, and no persistent pause or percentage-only thread move occurs.
Version
2.10.0; the relevant routing and quota-refresh behavior remained on dev at 075c2f34c060d068ed56985e76924a9f23aca39d when checked on 2026-08-03.
Operating system
Windows 11 Pro 10.0.26200 (platform-independent routing gap).
Provider and model
OpenAI (Codex login / forward account pool); native Codex models and confirmed quota scopes.
Logs or error output
Selected Codex account is cooling down
Screenshots and supporting files
None. Exact quota values, reset times, and account identifiers are omitted.
Redacted configuration
{
"providers": {
"openai": {
"adapter": "openai-responses",
"authMode": "forward",
"codexAccountMode": "pool"
}
},
"accountPoolStrategy": "fill-first",
"autoSwitchThreshold": 100,
"activeCodexAccountId": "__main__"
}
Checks
Client or integration
Codex App
Area
Authentication and account pool
Summary
A reset-derived Codex cooldown can remain after the account recovers early when another pool account remains eligible.
An actual upstream
429with reset headers creates a non-persistent cooldown. The cooled account is excluded, and the current recovery probe is acquired only after routing selects that account. If another account can always serve traffic, the cooled account is never selected, so it never receives the bounded probe. A forced fresh WHAM read may show recovery, but updating quota cache does not clear the matching routing cooldown.Persistently pausing an account at displayed
100%is not a valid workaround: OpenAI can reset earlier than the predicted timestamp,100%can remain advisory while an in-progress task still succeeds, and pause can outlive the restriction.Expected behavior:
100%snapshot alone must not create cooldown, pause, or move an existing thread.100%, incomplete, stale, unavailable, unrelated-scope, or replaced-credential results.Retry-Afteror headerless/default cooldowns through this path.Relevant source:
src/codex/routing.ts: reset-derived health, generations, scope, selection, and probe leases.src/codex/auth-context.ts: probe admission currently occurs only after selection.src/codex/auth-api.ts: main/pool forced refresh and existing single-flight.src/codex/quota.ts: freshness and authoritative exhaustion.Required tests: early recovery with another eligible account; still-exhausted/unknown/fetch-failure cases; concurrent single-flight; stale-generation rejection; main and pool accounts; shared vs Spark scope separation; explicit
Retry-Afteruntouched; all pool strategies re-include the recovered account;pausedunchanged; and no cooldown/rebinding from a standalone100%snapshot.Related: #433 (bounded probe/cap), #590/#599 (scoped cooldowns), #584/#585 (same-request failover after real rejection), and #657/#866 (separate reset-credit semantics).
Reproduction
429with reset headers.Current: A's quota cache updates, but its routing cooldown remains because A is never selected for the existing probe.
Expected: one bounded refresh clears only A's matching reset-derived generation, A becomes eligible immediately, and no persistent pause or percentage-only thread move occurs.
Version
2.10.0; the relevant routing and quota-refresh behavior remained ondevat075c2f34c060d068ed56985e76924a9f23aca39dwhen checked on 2026-08-03.Operating system
Windows 11 Pro 10.0.26200 (platform-independent routing gap).
Provider and model
OpenAI (Codex login / forward account pool); native Codex models and confirmed quota scopes.
Logs or error output
Screenshots and supporting files
None. Exact quota values, reset times, and account identifiers are omitted.
Redacted configuration
{ "providers": { "openai": { "adapter": "openai-responses", "authMode": "forward", "codexAccountMode": "pool" } }, "accountPoolStrategy": "fill-first", "autoSwitchThreshold": 100, "activeCodexAccountId": "__main__" }Checks