Skip to content

fix(codex): pace hard-lock recovery and quota retries #6153

Description

@terrytan95

Client or integration

OpenCodex dashboard

Area

Authentication and account pool

Summary

Two remaining ordinary Codex usage-query paths send avoidable authenticated requests after the automatic-activation scheduling fix (#6018 / #6020, landed via #6062):

  1. While the native main account is hard-locked, the minute sweep forces WHAM usage reads even when every blocking reset is already known to be in the future.
  2. Main/pool usage failures lack shared dispatch-level retry pacing. A failed read leaves the last-good cache expired, so later dashboard polls or other query owners can repeatedly retry. Pool non-auth HTTP errors do not honor Retry-After in the usage-fetch path.

Expected: preserve hard-lock protection but wait locally for its predicted reset before querying to confirm recovery; share failure backoff across ordinary account-list, background and forced usage queries. Never treat elapsed time or stale cached quota as proof of recovered capacity.

The operational motivation is fewer unnecessary authenticated requests and better session continuity. The reporting user associates frequent regular requests with forced sign-outs, but causation and improved account/session lifetime have not been measured. This issue makes no claim about OpenAI detection thresholds or guaranteed sign-out prevention.

Reproduction

Code-based reproduction, verified using mocked upstream responses rather than live-account probes:

  1. Seed the native main account's hard-lock policy snapshot with blocking usage and a reset one hour in the future. Run successive minute sweep hooks. The existing recovery function calls fetchMainAccountInfoAttempt(true, ...) without considering status.resetAt.
  2. For an ordinary pool account with an expired/missing quota snapshot, make WHAM return HTTP 429 with Retry-After: 900, HTTP 503, or a transport error.
  3. Repeat account reads every 30 seconds, including forced refreshes. The successful-cache TTL does not gate failed reads; the pool's generic non-401 branch simply returns old quota. Priming-specific throttles do not protect all callers.

Desired regression behavior: zero recovery usage calls before the known reset; one confirming query at/after reset; still-blocked or unknown-reset recovery no more often than every five minutes. HTTP/network failures should back off 5, 10, 20, 40, then 60 minutes and respect a longer bounded Retry-After. Replaced credentials must not inherit the failed credential's retry state. Deferred reads must expose neither fresh quota nor new dispatch evidence.

Version

Rechecked against v2.69.0 (3cc34e1) and dev eb7f0f0 (package 2.70.0).

Operating system

macOS 27.0; the inspected logic is platform-independent.

Provider and model

Canonical OpenAI Codex account usage (WHAM); model-independent.

Logs or error output

Source evidence: src/codex/auth-api/pool-mode-gate.ts runMainAccountHardLockRecovery, src/codex/auth-api/main-account-probe.ts, and src/codex/auth-api/pool-quota-probe.ts fetchFreshPoolAccountQuota / fetchPoolAccountQuota. No production traffic or credentials were captured.

Screenshots and supporting files

Regression coverage is supplied in the accompanying PR. Related: #6018, #6020, #6062. Reserve capability queries, login flows, and optional catalog refresh remain outside this issue.

Redacted configuration

Main hard-lock is enabled by default; explicit equivalent: {"codexMainAccountHardLock": true}. No new setting is proposed. Ordinary dashboard account reads demonstrate the failure-retry path without enabling automatic activation.

Checks

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

Activity

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

    account-poolOAuth, credentials, Codex pool, quota, failover, plansbugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions