Codex budget draining drastically since 2026-06-25: needs_follow_up loop + rate_limits.used_percent no longer reported
What issue are you seeing?
Starting around 2026-06-25, my Codex budget drains drastically faster than before on my $200/mo Pro subscription. For example, a single prompt ran for ~6 minutes and consumed tokens as if it were many prompts, with model_needs_follow_up=true looping repeatedly inside one turn. The 5h/weekly quota is gone within a handful of prompts.
Two concrete anomalies surfaced in the local log DB (~/.codex/logs_2.sqlite, table logs):
Anomaly 1 — rate_limits.used_percent stopped being reported
The structured rate_limits payload (with primary.used_percent / secondary.used_percent, window_minutes: 300 / 10080) that the server used to return disappeared after 2026-06-23. Per-day count of log rows containing used_percent:
| Date | Rows with used_percent |
|------|--------------------------|
| 2026-06-17 | 7 |
| 2026-06-18 | 9 |
| 2026-06-19 | 15 |
| 2026-06-20 | 16 |
| 2026-06-21 | 18 |
| 2026-06-22 | 24 |
| 2026-06-23 | 1 |
| 2026-06-24 | 0 |
| 2026-06-25 | 0 |
So there is currently no per-request primary/secondary usage feedback at all, while the budget itself drains fast — making it impossible to self-monitor.
Anomaly 2 — single turns loop on needs_follow_up=true, burning tokens
On a normal day (2026-06-17), a turn logged 1–3 post sampling token usage samples and the total_usage_tokens delta within a turn was small (e.g. 274, 1190). The 5h primary.used_percent moved gently: 4% → 7% → 8% → 18% → 21% across the day.
On 2026-06-25, 53 distinct turns produced 248 sampling rows, and all 53 turns logged model_needs_follow_up=true at least once (195 true samples vs 53 false terminations). 18+ turns hit ≥5 consecutive follow-up samples. Worst cases:
| Turn (redacted) | Samples | Duration | total_usage_tokens (min→max) | Delta |
|-----------------|:-------:|:--------:|:------------------------------:|:-----:|
| Turn A | 23 | 6m39s | 52,643 → 174,494 | +121,851 |
| Turn B | 22 | 8m00s | 63,223 → 177,705 | +114,482 |
| Turn C | 17 | 2m45s | 100,642 → 136,349 | +35,707 |
| Turn D | 15 | 2m39s | 127,175 → 174,340 | +47,165 |
| Turn E | 6 | 2m02s | 47,005 → 246,323 | +199,318 |
Timeline of Turn A (one prompt, medium reasoning effort, gpt-5.4), total_usage_tokens sampled every few seconds with needs_follow_up=true the whole way until the final sample:
10:02:01 52,643 needs_follow_up=true token_limit_reached=false
10:02:11 75,811 needs_follow_up=true token_limit_reached=false
10:02:20 96,564 needs_follow_up=true token_limit_reached=false
10:02:29 108,338 needs_follow_up=true token_limit_reached=false
10:02:41 116,197 needs_follow_up=true token_limit_reached=false
10:03:08 120,191 needs_follow_up=true token_limit_reached=false
10:03:33 133,647 needs_follow_up=true token_limit_reached=false
10:04:35 139,440 needs_follow_up=true token_limit_reached=false
10:04:52 140,543 needs_follow_up=true token_limit_reached=false
10:05:15 142,253 needs_follow_up=true token_limit_reached=false
10:05:28 143,108 needs_follow_up=true token_limit_reached=false
10:06:09 146,222 needs_follow_up=true token_limit_reached=false
10:06:32 147,421 needs_follow_up=true token_limit_reached=false
10:07:01 149,644 needs_follow_up=true token_limit_reached=false
10:07:10 158,442 needs_follow_up=true token_limit_reached=false
10:07:21 159,801 needs_follow_up=true token_limit_reached=false
10:07:55 162,505 needs_follow_up=true token_limit_reached=false
10:08:03 169,054 needs_follow_up=true token_limit_reached=false
10:08:08 171,675 needs_follow_up=true token_limit_reached=false
10:08:21 172,491 needs_follow_up=true token_limit_reached=false
10:08:27 173,597 needs_follow_up=true token_limit_reached=false
10:08:32 174,494 needs_follow_up=true token_limit_reached=false
10:08:40 174,494 needs_follow_up=false token_limit_reached=false
This looks like a needs_follow_up loop: the model keeps requesting follow-up within a single turn, tokens accumulate monotonically, and only a false terminates it — by which point one prompt has cost ~122k–199k tokens. This matches the community reports in #28879 (per-token limit cost up 10–20× since ~June 16) and #14593.
What steps can reproduce the bug?
- Codex desktop app, macOS arm64, gpt-5.4 / gpt-5.5, default service tier, reasoning effort medium/xhigh.
- Send a reasonably simple prompt.
- Observe in
~/.codex/logs_2.sqlite(target='codex_core::session::turn') that the turn logs many consecutivemodel_needs_follow_up=truesamples with monotonically increasingtotal_usage_tokens, and that norate_limits.used_percentpayload is returned anymore.
No fast mode, no multi_agent, no large-context flag, no manual feature flags.
What is the expected behavior?
- Per-request
rate_limits(primary/secondaryused_percent) should be reported consistently, as it was through 2026-06-23, so users can monitor 5h/weekly usage. - A single turn should not loop on
needs_follow_up=truefor minutes, accumulating 100k–200k tokens for one prompt. Token consumption per prompt should be in the same ballpark as before 2026-06-24.
Additional information
- Subscription: Pro ($200/mo).
- Log DB:
~/.codex/logs_2.sqlitetablelogs,target='codex_core::session::turn'andtarget='codex_api::endpoint::responses_websocket'. - All turn/thread IDs and local file paths in this report have been redacted.
- Related: #28879, #14593.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗