codex - 💡(How to fix) Fix TUI blocks all models when primary bucket hits 100%, even models that are not actually rate-limited

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When a long-running codex TUI session sees rate_limits.primary.used_percent reach 100% (regardless of which model triggered it), the session refuses to send further requests on any model — including models the server is not actually blocking, like gpt-5.3-codex-spark on a prolite plan.

A fresh codex session started in a new terminal works fine on the same model that the affected terminal refuses to use. The web portal correctly shows separate usage stats for spark vs. the main models, but the CLI's rate-limit envelope conflates them into a single limit_id: "codex" bucket.

Root Cause

When a long-running codex TUI session sees rate_limits.primary.used_percent reach 100% (regardless of which model triggered it), the session refuses to send further requests on any model — including models the server is not actually blocking, like gpt-5.3-codex-spark on a prolite plan.

A fresh codex session started in a new terminal works fine on the same model that the affected terminal refuses to use. The web portal correctly shows separate usage stats for spark vs. the main models, but the CLI's rate-limit envelope conflates them into a single limit_id: "codex" bucket.

Fix Action

Fix / Workaround

Users hitting the primary bucket lose access to spark in any pre-existing terminal even though their spark allowance is unused. They must quit and restart codex to recover access. For long-running terminal sessions (tmux panes, persistent agents), this is a forced session loss with no workaround inside the running TUI.

Code Example

{
  "limit_id": "codex",
  "primary": {
    "used_percent": 100.0,
    "window_minutes": 300,
    "resets_at": ...
  },
  "secondary": { "used_percent": 62.0, "window_minutes": 10080, ... },
  "credits": { "has_credits": false, "balance": "0" },
  "plan_type": "prolite",
  "rate_limit_reached_type": null
}

---

if rate_limits.primary.used_percent >= 100: block_request()

---

if rate_limits.rate_limit_reached_type is not None: block_request()
RAW_BUFFERClick to expand / collapse

Summary

When a long-running codex TUI session sees rate_limits.primary.used_percent reach 100% (regardless of which model triggered it), the session refuses to send further requests on any model — including models the server is not actually blocking, like gpt-5.3-codex-spark on a prolite plan.

A fresh codex session started in a new terminal works fine on the same model that the affected terminal refuses to use. The web portal correctly shows separate usage stats for spark vs. the main models, but the CLI's rate-limit envelope conflates them into a single limit_id: "codex" bucket.

Reproduction

  1. Start codex on gpt-5.5 (or whatever the default primary model is on a prolite plan)
  2. Burn through the 5-hour primary bucket until rate-limits return 100% on the primary window
  3. In a separate codex terminal already running gpt-5.3-codex-spark, attempt to send a message
  4. The spark terminal refuses to send, even though server-side spark is not blocked
  5. Open a brand-new terminal, launch codex, switch to gpt-5.3-codex-spark → works immediately on the same account

Expected Behavior

The TUI should use rate_limit_reached_type (the explicit server signal) to decide whether to block a request, not primary.used_percent alone. When rate_limit_reached_type: null, the server is permitting the request and the client should send it.

Alternatively, the rate-limit envelope should be enriched server-side to distinguish per-model availability the way the web portal does.

Evidence

I inspected a past spark session from a prolite account where rate_limits.primary.used_percent was 100% the entire time:

{
  "limit_id": "codex",
  "primary": {
    "used_percent": 100.0,
    "window_minutes": 300,
    "resets_at": ...
  },
  "secondary": { "used_percent": 62.0, "window_minutes": 10080, ... },
  "credits": { "has_credits": false, "balance": "0" },
  "plan_type": "prolite",
  "rate_limit_reached_type": null
}

That session logged 2275 successful response events at primary=100%. The server allows spark at 100% primary — the field rate_limit_reached_type: null confirms it.

Impact

Users hitting the primary bucket lose access to spark in any pre-existing terminal even though their spark allowance is unused. They must quit and restart codex to recover access. For long-running terminal sessions (tmux panes, persistent agents), this is a forced session loss with no workaround inside the running TUI.

Environment

  • codex-cli 0.130.0
  • Plan: prolite
  • Default model: gpt-5.5
  • Affected model when this happens: gpt-5.3-codex-spark

Suggested Fix

In the TUI's request gate, change the decision from:

if rate_limits.primary.used_percent >= 100: block_request()

to:

if rate_limits.rate_limit_reached_type is not None: block_request()

The used_percent: 100 value is informational (drives the UI meter), not authoritative for whether a specific request will be allowed. The authoritative signal is rate_limit_reached_type.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix TUI blocks all models when primary bucket hits 100%, even models that are not actually rate-limited