Skip to content

[OpenAI/Codex] K12 5-hour quota is mislabeled as weekly and the real weekly window is discarded #1791

Description

@jojodat

Client or integration

OpenCodex dashboard

Area

Authentication and account pool

Summary

The WHAM response for plan_type: "k12" contains two simultaneous limiting windows:

  • primary: 18,000 seconds (rolling 5 hours)
  • secondary: 604,800 seconds (7 days)

OpenCodex stores the primary 5-hour value in weeklyPercent / weeklyResetAt and discards the actual weekly secondary window. Consequently, the dashboard labels the 5-hour value and reset as Week, while the real weekly usage is neither shown nor considered independently for routing.

At the same observation point, official Codex Analytics showed 99% remaining for the 5-hour limit and 100% remaining for the weekly limit. OpenCodex showed/stored weekly 1%. Converting remaining to used makes the values match exactly, proving the primary window was mislabeled rather than merely stale.

Reproduction

  1. Add a ChatGPT Codex pool account whose WHAM plan is k12.
  2. Force a quota refresh with ocx account refresh openai or Refresh quotas.
  3. Observe that OpenCodex reports only weekly 1% and uses the primary window's reset.
  4. Compare with the sanitized WHAM structure below: primary is 5 hours at 1% used; secondary is 7 days at 0% used.
  5. Compare with official Codex Analytics: 5-hour limit 99% remaining; weekly limit 100% remaining.

The separate K12 request/reauth regression is tracked in #1789. Quota refresh succeeds with HTTP 200, so this parser defect reproduces independently.

Version

2.20.0

Operating system

macOS (arm64; exact OS version omitted because the defect is not platform-specific)

Provider and model

OpenAI / ChatGPT Codex workspace login (plan_type=k12); WHAM usage endpoint

Logs or error output

Sanitized WHAM structure. The real absolute reset timestamps were replaced with synthetic integers; only their numeric type and primary/secondary association matter to this bug:

{
  "plan_type": "k12",
  "rate_limit": {
    "primary_window": {
      "used_percent": 1,
      "reset_at": 2000000000,
      "limit_window_seconds": 18000
    },
    "secondary_window": {
      "used_percent": 0,
      "reset_at": 2000586800,
      "limit_window_seconds": 604800
    },
    "tertiary_window": null
  },
  "rate_limit_reset_credits": {
    "available_count": 0
  }
}

Current OpenCodex projection of the same structure:

{
  "weeklyPercent": 1,
  "weeklyResetAt": 2000000000,
  "resetCredits": 0
}

Implementation clues in v2.20.0:

  • StoredAccountQuota in src/codex/quota.ts has weekly/monthly fields but no 5-hour fields.
  • parseUsageQuota() assigns a non-monthly primary window to weeklyPercent and only uses the secondary window as a fallback.
  • Codex routing/exhaustion evaluates weekly/monthly values, so discarding the true weekly window can affect account eligibility, not just the label.

Expected:

  • Classify windows by limit_window_seconds (18,000 = 5h; 604,800 = 7d).
  • Preserve and display both windows with their own reset values.
  • Treat the account as exhausted/unavailable when either governing window is exhausted.
  • Add parser, cache, dashboard, and routing tests for a K12 two-window payload.

Screenshots and supporting files

Related K12 authentication/workspace issue: #1789

Redacted configuration

{
  "codexAccounts": [
    {
      "plan": "k12",
      "isMain": false
    }
  ]
}

Emails, account/workspace IDs, bearer and refresh tokens, request IDs, original reset timestamps, timezone, and local paths were removed.

Checks

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

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