Skip to content

[Bug]: 2.42.0 Plus quota exhaustion causes 18 incomplete failures without switching to main (related to #3795) #3994

Description

@FacuM

Client or integration

Codex Responses traffic through the local OpenCodex proxy. Configured Codex runtime: 0.153.4.

Area

Authentication and account pool

Summary

On an installation whose package.json reports 2.42.0, an exhausted ChatGPT Plus pool account received 18 consecutive quota failures without automatic failover to the main account. Auto-switch threshold was configured as 95%. Subsequent requests using the main account succeeded.

Known-bug field confirmation, not a claim of a regression on current releases: this matches the incomplete-terminal accounting defect in #3795, fixed by #3791. The maintainer confirmed that fix in v2.46.0. This report adds a short-window exhaustion occurrence and sanitized evidence from 2.42.0; it can be linked/closed as a duplicate of #3795. No reproduction on v2.46.0 or v2.47.0 has been performed.

Expected: quota-bearing incomplete terminals should update account health and allow the next eligible non-fixed request to select a healthy account. This does not require replaying an already-started stream.

Reproduction

Observed production sequence (not a newly executed live quota-exhaustion test):

  1. Configure main plus one additional ChatGPT Plus account, with autoSwitchThreshold: 95.
  2. Send ordinary native-model Responses requests using bare gpt-6-astra (not an explicit account namespace).
  3. Exhaust the Plus account's five-hour window.
  4. Continue sending requests. In this occurrence, 18 consecutive requests remained on that account, each logging The usage limit has been reached, status 502, and terminal incomplete.
  5. Requests subsequently routed to main and returned 200. The on-disk configuration inspected afterward had main active and manually pinned. The logs establish recovery on main, but do not by themselves establish who/what initiated that account change.

Version

2.42.0 from the installed @bitkyc08/opencodex/package.json. Exact running process revision was not independently captured.

Operating system

Linux 6.19.11-1-cachyos, x86_64 GNU/Linux.

Provider and model

OpenAI / ChatGPT Codex account pool, gpt-6-astra, native-family routing, Responses protocol, loopback admission.

Logs or error output

Sanitized aggregation from local usage.jsonl, all times UTC on 2026-09-08:

First Plus quota failure:     03:14:25.098
Last Plus quota failure:      03:15:38.060
Consecutive quota failures:   18
Attempts per failed request:  1 (all 18)
Recovery kinds:               [] (all 18)
First subsequent main 200:    03:16:01.316

status:          502
errorCode:       upstream_server_error
upstreamError:   The usage limit has been reached
terminalStatus:  incomplete
closeReason:     terminal
usageStatus:     unreported
requestedModel:  gpt-6-astra
routeKind:       native
selected.reason: native-family

Persisted quota snapshot inspected after the event:

Plus snapshot updatedAt: 2026-09-08T03:14:03.135Z
Plus shortPercent: 100
Plus shortWindowSeconds: 18000
Plus shortResetAt: 1788840169
Plus weeklyPercent: 16
Main weeklyPercent: 11

Main's short-window percentage was absent, not measured as zero. The disk snapshot does not prove that the serving process used that same in-memory snapshot for every failed admission.

Source inspection and likely mechanism

The installed source still contains the known pre-fix behavior:

  • src/server/responses/core.ts:1382-1395, codexForwardTerminalOutcomeRecorder: every status === "incomplete" unconditionally calls recordCodexUpstreamOutcome(..., 200, ...) and returns, clearing failure evidence rather than recording quota exhaustion.
  • src/server/request-log.ts:874: after the policy check, captureTerminalHttpStatus returns for anything other than response.failed; it does not classify an incomplete quota message as semantic 429/402.

This explains the missing quota-health signal despite a visible 502 in request logs and matches #3795/#3791. The additional question of why the persisted short-window snapshot did not prevent those admissions cannot be conclusively answered from these files alone; do not interpret this report as proof of a separate selector defect.

Redacted configuration

Relevant observed settings (account identifiers replaced):

{
  "autoSwitchThreshold": 95,
  "codexAccountPriorities": {"PLUS_ACCOUNT": 2},
  "codexAccounts": [{"id": "PLUS_ACCOUNT", "plan": "plus", "isMain": false}],
  "activeCodexAccountId": "__main__",
  "activeCodexAccountPinned": "__main__"
}

The active/pinned fields are the post-incident state, not an assertion about the state before exhaustion. No configuration, credentials, installed code, or service state was modified during this investigation.

Checks

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