[Bug] Stale Codex resets_at blocks paid account failover after the account is already usable
Is it a request payload issue?
- Yes
- No, it is a persisted Codex quota/cooldown issue.
Describe the bug
A paid Codex OAuth account can remain excluded from routing until an old usage_limit_reached.resets_at deadline even after the same account is accepted by upstream again.
In a two-account pool, account B was kept in a persisted model cooldown. When account A later exhausted its quota, failover failed because both credentials were considered locally unavailable. Restarting CLIProxyAPI did not help because save-cooldown-status: true restored the cooldown. Toggling account B disabled -> active cleared the local state, and the next request through account B immediately returned HTTP 200, about 98 hours before the cached deadline.
No upstream quota reset, OAuth re-login, token refresh, or credential replacement was performed during recovery; the logs show only Management API status PATCHes.
Timeline (local time, UTC+4)
2026-08-31 01:05:14 account B upstream 429:
type=usage_limit_reached plan_type=pro
resets_at=1788643357 (2026-09-06 01:22:37 +04)
resets_in_seconds=519443
-> local cooldown=144h17m22s
2026-09-01 22:32:07 account A upstream 429:
type=usage_limit_reached plan_type=pro
resets_at=1788747928 (2026-09-07 06:25:28 +04)
resets_in_seconds=460401
2026-09-01 22:32:19 selector:
2 of 2 candidates are in cooldown
account A remaining=127h53m08s
account B remaining=98h50m17s
2026-09-01 23:36:37 CLIProxyAPI 7.2.147 restarted
2026-09-01 23:37:50 both cooldowns were restored; account B remaining=97h44m46s
2026-09-01 23:47:10 PATCH /v0/management/auth-files/status (account B disabled)
2026-09-01 23:47:11 PATCH /v0/management/auth-files/status (account B active)
2026-09-01 23:47:17 selector chose account B
2026-09-01 23:47:19 POST /v1/responses -> HTTP 200
This confirms that the cached paid-plan deadline no longer represented actual upstream availability, while CLIProxyAPI had no request path that could observe the recovery.
Expected behavior
A paid Codex credential that becomes usable before an old advertised deadline should eventually be reconsidered without requiring an operator to clear its cooldown manually. This should be bounded/backed off rather than a tight polling loop.
Actual behavior
parseCodexRetryAfter uses the full future resets_at, the model state is persisted to .cds, restored after restart, and filtered before any upstream request. request-retry cannot help because no eligible credential reaches the executor.
CLI Type
Codex OAuth, two ChatGPT Pro accounts.
Model Name
gpt-5.6-sol
LLM Client
Codex app / codex-tui 0.151.0, Responses API.
Request Information
POST /v1/responses. This is not payload-dependent; consecutive requests were rejected locally in 8-16 ms while both auths were in cooldown. The first request after clearing only the local auth state succeeded through upstream in 1.895 s.
Environment
- CLIProxyAPI
7.2.147, commit17a65ee5 - macOS 26.6.2, arm64
routing.strategy: fill-firstsave-cooldown-status: truedisable-cooling: falserequest-retry: 3- WebSocket-capable Codex OAuth auths
Related
- #5277 describes stale cooldown after an explicit upstream quota reset; it was closed in favor of manual
POST /v0/management/reset-quota. - #4248 already proposes a bounded paid-plan recheck. This report provides a current v7.2.147 real-world reproduction where no upstream reset action was performed and stale cooldown prevented two-account failover.
Source: router-for-me/CLIProxyAPI