Skip to content

Paid-credit-enabled Codex pool can remain locally quota-held after its credit observation expires #8145

Closed as not planned

Description

@JJONGFILM

Reported reproduction

The operator's 2026-11-03 investigation found local image requests failing immediately with HTTP 429
(rate_limit_exceeded, provider unknown, roughly 3ms). The shared Pro accounts had full weekly
windows, paid-credit spending already enabled and positive cached balances. Requests never reached
an upstream account. A manual ocx account refresh openai on one affected device was followed by an
image HTTP 200 at 15:36:57 KST. Other devices were manually refreshed too; their individual recovery
is not independently verified by this implementation. The supplied plan is the source of those
operational observations; this worker did not run refresh on any operational device or alter the
existing manual-refresh records.

  1. Use a local OpenAI Codex pool with an exhausted included-plan window.
  2. Explicitly enable credits after limit for the account and retain a positive spendable balance.
  3. Let the credit observation become stale while quota remains full.
  4. Send an image request through the pool; observe a local 429 with no upstream attempt.
  5. Refresh quota/credits, then retry a small independent image self-test.

Source-based explanation

The installed opencodex 2.95.0 source inspected read-only uses a separate five-minute credit observation clock (this is not an operational device version verification):
src/codex/quota-types.ts (CODEX_CREDITS_FRESHNESS_MS, hasSpendableCodexCredits).
src/codex/account-credit-use.ts (isCodexAccountHeldForCredits) requires both existing account
consent and a fresh spendable balance to retain a fully used account. A positive old balance alone
is insufficient. A locally held account cannot re-observe its balance through requests that never
reach it. The account list projection carries consent but drops spendable credit details, so the
workaround joins the local quota cache to current eligible account ids without reading credentials.

Primary source links (moving main; local source files were inspected for this draft):

This is an inference from the inspected routing conditions plus the operator's reproduction, not
proof that every local 429 has this cause. A remote provider throttle, a paused account, missing
consent, reauthentication, spending veto and zero balance must remain distinct.

Suggested upstream change

For already opted-in accounts that are held only because a spendable credit observation is stale,
refresh quota/credit observations with a per-pool single flight and finite retry/cooldown budget.
Re-evaluate selection only from the fresh answer. Preserve operator exclusions, auth failures,
provider throttles and account identity binding. Do not enable credit spending, redeem reset
credits, select another identity or treat an unavailable balance as spendable.

Consider an explicit local rejection reason and a sanitized credit observation state in the account
DTO. This would let clients distinguish no credits from stale/unavailable observations without
parsing the persisted cache or inspecting request timing.

ohmyhub workaround and validation

As of 2026-11-04 (ohmyhub f74403f, deployed to our workers the same day), ohmyhub keeps the
credit observation of already opted-in, exhausted accounts alive by running a refresh about every
two minutes, which is shorter than the five-minute freshness window, and has no hourly attempt cap.
It also re-checks the observation before accepting work and before the self-test image. Refreshes
are single-flight per device, and the two-minute minimum spacing is persisted across restarts
(failed attempts count). Before this change it refreshed only after usage exhaustion or a
quota-full local image 429, with at least five minutes between attempts and at most three
attempts per rolling hour. A new decoded PNG is required before old OpenAI usage holds can be
released. Hub clients,
API key accounts and credit opt-outs keep their existing policy. Regression tests use a fake local
opencodex executable and a local HTTP server; they do not call any real provider.

No account, balance, email, token or production request body is included in this report.

Activity

  1. coderabbitai commented on Nov 3, 2026

    @coderabbitai
    Contributor
    🔗 Related PRs

    #7474 - [WRONG BRANCH] release: promote dev 845ac6b to main as 2.90.0 [merged]


    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  2. github-actions commented on Nov 3, 2026

    @github-actions
    Contributor

    Automated translation bookkeeping — detected language: English.

  3. github-actions commented on Nov 3, 2026

    @github-actions
    Contributor

    Issue closed: use an issue template

    Thanks for taking the time to submit this issue. It was closed automatically because it was not opened with a recognized issue template (Bug report, Feature request, Documentation, or Provider compatibility). Freeform and API-opened issues cannot skip this check.

    • This issue does not use a recognized issue template.

    Please edit the issue to add:

    • Open a new issue with the Bug report, Feature request, Documentation, or Provider compatibility template.
    • Or edit this issue so the body uses the template section headings for the kind of report you are filing.

    See the Contributing guide for details.

    Once the report passes the automated checks, it will be reopened automatically unless a maintainer has changed its state.

  4. github-actions commented on Nov 3, 2026

    @github-actions
    Contributor

    Potential duplicates found:

    Reason: Issue 7377 reports the identical mechanism: a Codex pool account opted into credits creditCodexAccountIds with a positive balance and a full 5h window gets dropped from rotation once its credit read becomes stale 5 minutes, causing requests

    Detected automatically via GitHub Copilot; automatic closure requires separate deterministic evidence.

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, plans

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions