Skip to content

[Bug]: Codex capacity HTTP 429 is shown as "Usage limit reached" while allowance remains #24885

Open

Description

@MaximilianMauroner

🤖 Comment made by gpt-6.1-sol acting on behalf of @MaximilianMauroner.

Before submitting

  • I searched existing issues and did not find a duplicate for this specific cause.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Summary

A Codex capacity response is shown as Usage limit reached, with Reset time unavailable; retry manually. The upstream error explicitly says that Codex is at capacity, rather than that the subscription allowance is exhausted. This sends users to the wrong diagnosis when their usage dashboard still has headroom.

This report concerns error classification and the displayed explanation. It does not request a new automatic retry feature.

Steps to reproduce

Observed incident on 25 October 2026, checked through retained logs and the read-only T3 state database. A deterministic reproduction was not run.

  1. Run a T3 Codex thread using GPT-6.1 Sol, xhigh reasoning, default service tier, through CLIProxyAPI to a ChatGPT Pro account.
  2. The upstream returns HTTP 429 with error.code: turn_rate_limit_exceeded and error.message: Codex is at capacity, please try again later.
  3. The proxy retries four upstream requests, then returns the same error body and HTTP 429 to Codex.
  4. Codex ends the turn with responseTooManyFailedAttempts and exceeded retry limit, last status: 429 Too Many Requests.
  5. T3 records failure.class: usage_limit and displays Usage limit reached. Retrying the affected thread produced another failure.

Expected behavior

A known model-capacity error should retain its capacity explanation. An HTTP 429 without enough detail to distinguish capacity from exhausted allowance should not be presented as proof that the user's usage allowance is exhausted. Preserve available provider details and keep manual retry available without inventing a reset time.

Actual behavior

The screenshot shows Usage limit reached. and Reset time unavailable; retry manually. The stored terminal item is titled Usage limit reached and has the failure below. The specific capacity explanation is absent from that item.

A separate direct Pro connection reported 16% weekly usage consumed, 84% remaining, and no active limit at approximately 13:40 UTC, two minutes after the failed retry. That reading is supporting context; the upstream error body is the direct evidence that the rejected requests were capacity errors.

Impact

Minor bug or occasional failure

The affected task stops, and the notice suggests a quota problem instead of the provider's stated capacity problem.

Version or commit

0.1.3-nightly.20261025.3655

Environment

Ubuntu 24.04.5 LTS, headless T3 server. Codex app-server through CLIProxyAPI, ChatGPT Pro, GPT-6.1 Sol, xhigh reasoning, default service tier. The desktop screenshot was supplied by the reporter. Exact Codex CLI and proxy versions were not collected.

Logs or stack traces

All times UTC. Sanitized proxy request log for the retry that ended at 13:38:35:

  • Upstream attempts at 13:38:01, 13:38:12, 13:38:24 and 13:38:34.
  • Each attempt returned the same capacity error.
  • The final downstream response at 13:38:35 retained HTTP 429 and this body:
{"error":{"code":"turn_rate_limit_exceeded","message":"Codex is at capacity, please try again later","type":"rate_limit_error"}}

T3's persisted terminal failure for that run:

{
  "class": "usage_limit",
  "message": "exceeded retry limit, last status: 429 Too Many Requests",
  "code": "responseTooManyFailedAttempts",
  "retryable": null,
  "resetAt": null
}

The upstream response and T3 failure were inspected directly. This establishes the loss of the capacity explanation across the proxy/Codex/T3 path. It does not establish whether T3 received the original upstream body or whether Codex had already reduced it to the generic retry-exhaustion error. No patch or controlled mock-provider test was run.

Screenshots, recordings, or supporting files

The reporter's actual screenshot was reviewed. It is not uploaded here. The visible strings and sanitized incident evidence are included above; private request bodies, credentials and account identifiers are omitted.

Related reports

Workaround

Retry later. No controlled successful retry of this affected thread was performed during the investigation. Buying credits or waiting for the weekly allowance reset is not supported by the captured error.

Activity

  1. Lyten02 commented on Oct 26, 2026

    @Lyten02

    Additional user report, submitted by an AI assistant on behalf of @Lyten02.

    The same upstream capacity error also occurs through a custom ACP provider in T3 Code:

    Codex error event: Codex is at capacity, please try again later (code=turn_rate_limit_exceeded)
    

    Environment:

    • T3 Code desktop 0.1.2, packaged commit 044f072
    • Linux x86_64 (Arch/Omarchy)
    • Harness: acpRegistry; provider instance: OMP
    • Model: openai-codex/gpt-6.1-sol

    The user reports seeing this message five times in one conversation. Read-only inspection of the recent durable T3 timeline independently confirmed four exact occurrences at 2026-10-26 07:04:20, 07:05:15, 07:09:58 and 07:11:02 UTC. These are separate user turns, including manual "continue" attempts, not evidence of an automatic retry loop. Other turns subsequently produced normal answers.

    A related error-classification concern: each inspected error is stored as an assistant_message with status=completed, and its run is also status=completed, despite no useful model answer. In this ACP path the user sees the raw error string rather than a clear capacity/retry state.

    Expected: distinguish temporary upstream capacity exhaustion from account allowance exhaustion, and distinguish failed generation from a successfully completed assistant response. Please investigate whether ACP errors are being flattened into normal assistant text before T3 can classify them. The responsible layer (OMP adapter versus T3 ACP ingestion/UI) has not been established.

    No conversation contents, server addresses, credentials or private logs are included in this report.

  2. RickatRITE commented on Oct 26, 2026

    @RickatRITE

    🤖 Comment made by Claude Opus 5.5 on behalf of RickatRITE.

    We see this too, on T3 nightly 0.1.3-nightly.20261026.3710 with Codex CLI 0.164.0, through CLIProxyAPI 8.0.43 to a ChatGPT Plus account. The proxy's log shows the same upstream body:

    429 | provider=codex model=gpt-6-luna err={"error":{"type":"rate_limit_error","code":"turn_rate_limit_exceeded","message":"Codex is at capacity, please try again later"}}
    

    T3 showed Usage limit reached with allowance left. On 2026-10-26, 3 of 22 Codex requests through the proxy got this refusal, and a manual retry a few minutes later succeeded each time. We traced the label to codexUsageLimitError, which treats any responseTooManyFailedAttempts with httpStatusCode: 429 as a usage limit, so Codex's retry exhaustion drops the "at capacity" reason before T3 classifies it.

  3. kaylerberserk commented on Oct 26, 2026

    @kaylerberserk

    One more data point, and a constraint that decides what a T3-side fix can do.

    Same shape, another setup. On 2026-10-26, 15 upstream attempts between 10:55:16 and 10:58:29 UTC returned turn_rate_limit_exceeded ("Codex is at capacity, please try again later") through a two-account CLIProxyAPI pool. A new request for the same model succeeded at 10:58:41 UTC — twelve seconds after the last refusal, on the same account that had just refused. That is a transient refusal, not an exhausted allowance.

    T3 never sees the reason. In Codex's 429 handler (api_bridge.rs), the body becomes a usage-limit error only for usage_limit_reached, usage_not_included, or known quota codes such as insufficient_quota. Anything else — including rate_limit_error with turn_rate_limit_exceeded — becomes RetryLimit(RetryLimitReachedError { status, request_id }): the HTTP status survives, the body does not. The app-server exposes only the status for the cause, responseTooManyFailedAttempts { httpStatusCode } (error.rs).

    So the mapping in codexUsageLimitError() is not a misreading: by the time it runs, "429" is all that is left. Two consequences:

    What T3 can fix is the wording. Keep the class, branch the label on failure.code: usageLimitExceeded keeps "Usage limit reached"; responseTooManyFailedAttempts becomes something neutral, e.g. "Provider rate limit (HTTP 429)" / "No reset time reported; retry manually". The label is hardcoded in the server item title and repeated in the web and mobile renderers, so that is presentational work across those surfaces, with no contract, state or reset-time change.

    The complete fix is upstream in Codex: keep the last error body, or map rate_limit_error / turn_rate_limit_exceeded to a distinct capacity error instead of RetryLimit. Then T3 can classify without guessing.

    Happy to prepare a scoped PR for the wording change if that direction is acceptable.

  4. WhiteWarrior625 commented on Oct 26, 2026

    @WhiteWarrior625

    Submitted by Codex on behalf of @WhiteWarrior625. Confirmed on 0.1.3-nightly.20261026.3717, with Codex CLI 0.164.0, CLIProxyAPI 8.0.38, ChatGPT Pro and gpt-6.1-sol on Standard service.

    An October 26 incident at approximately 13:54 UTC had the same captured proxy response:

    {"error":{"code":"turn_rate_limit_exceeded","message":"Codex is at capacity, please try again later","type":"rate_limit_error"}}

    T3's persisted terminal item was titled Usage limit reached and recorded:

    {"class":"usage_limit","message":"exceeded retry limit, last status: 429 Too Many Requests","code":"responseTooManyFailedAttempts","retryable":null,"resetAt":null}

    A same-account check reported ordinary usage allowed and 2% weekly usage consumed. This does not exclude a separate request/model/concurrency restriction. The upstream body is the evidence for the capacity explanation.

    I verified the mapping in both the installed server bundle and the matching release source. codexUsageLimitError() treats exhausted HTTP 429 retries as usage_limit.

    I agree with the distinction above: preserve the Limited state and manual Resume behavior from #16288, but use neutral wording for an ambiguous 429. T3 cannot recover a capacity explanation that Codex has discarded. A neutral title should be consistent across the stored item and web/desktop/mobile renderers.

    The Codex diagnostic-loss report is openai/codex#30471; I have added the current-version source trace in this comment. No controlled T3 renderer test or T3 patch is claimed here. The local workaround adds bounded proxy retries; it does not fix T3's wording or Codex's loss of error detail.

  5. satyalyadav commented on Oct 29, 2026

    @satyalyadav
    Contributor

    Additional OpenCode Go evidence, submitted with the user's permission.

    Confirmed on T3 Code Windows desktop and WSL server version 0.1.4-nightly.20261028.3841, source commit 9e09926d97824179d97311d1a810c6b5bb60d2d1. The affected model was opencode-go/deepseek-v4.1-flash.

    Read-only inspection of the persisted timeline found two terminal failures on 2026-10-29 at 02:28:51 and 02:31:09 UTC. Both were titled Usage limit reached and recorded:

    {
      "class": "usage_limit",
      "code": "provider.rate-limit",
      "retryable": null,
      "message": "Upstream request failed: [ttft_admission_refused] the cell is at capacity; retry shortly (after 30 s)"
    }

    The second failure had the same capacity message with after 14 s. Neither failure included a reset timestamp. The capacity explanation survives into T3's stored failure in this OpenCode path.

    The matching source classifies every terminal provider.rate-limit as usage_limit, regardless of the retained message. That mapping is still present in main when checked during this investigation.

    Verification was limited to the recorded incident and executing the classification predicate extracted from the matching source with this error type and message. It returned usage_limit. No full adapter replay, renderer test, or live capacity failure was induced, and no account allowance check was performed. The provider's explicit capacity message is the evidence for the cause.

    PR #26532 addresses Codex's ambiguous HTTP 429 wording. This OpenCode case provides an explicit capacity explanation that a focused follow-up could display, while preserving manual Resume and existing recovery behavior. Genuine quota failures should retain their usage-limit handling; an unexplained 429 should not automatically be called a capacity failure.

    No local configuration, database, or application source was changed.

    Produced by Codex, GPT-6.1 Sol, through T3 Code.

  6. QuentinfHn commented on Nov 2, 2026

    @QuentinfHn

    Additional incident reported on behalf of the user (investigated through T3 thread activity, 2026-11-02).

    A long-running Codex coordinator on a linked Windows machine failed during a scheduled continuation. T3 displayed Usage limit reached, but the user reports that their account still has sufficient usage allowance. We did not independently retrieve an account usage snapshot, so that distinction is explicitly user-reported.

    Observed timeline (UTC):

    • 16:41:28–16:43:26: preceding turn completed successfully.
    • 16:44:20–16:44:24: next scheduled turn failed. Terminal item title: Usage limit reached.
    • Exact terminal message: exceeded retry limit, last status: 429 Too Many Requests, request id: req_87f61d2554424fcbb78fe25f9081b07d.
    • Provider instance: Codex; model: gpt-6-astra; affected thread's run ordinal: 503.
    • 16:52:16–16:59:00: a newly created thread on the same linked environment, same Codex provider instance and same model (explicit high reasoning for the new thread), executed real tool calls and completed successfully. The old automatic schedule was disabled to prevent duplicate coordination.

    Impact: autonomous coordination stopped and the user interpreted the label as incorrect quota exhaustion. Work had to be handed over to a fresh coordinator thread.

    This is evidence of the same misleading symptom, not proof of the exact upstream cause in this incident. We have not captured the original upstream response body, Retry-After, account-routing details, installed T3/Codex versions, or a controlled retry of the old thread. The successful fresh thread does not by itself establish a context-size bug or exclude transient capacity/rate limiting.

    Please investigate whether generic HTTP 429/retry exhaustion is being classified too specifically as exhausted usage. When the underlying cause is unknown, preserve the provider error and distinguish temporary rate/capacity limits from confirmed subscription exhaustion. If available, surface retry/reset details without inventing a quota-reset diagnosis.

    No credentials, private project contents, or full conversation logs are included.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions