Repository navigation
[Bug]: Codex Business workspace credit exhaustion shows as a generic runtime error, not a usage-limit stop #9234
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- Sign Codex in with a ChatGPT Business workspace account (Team/Enterprise behave the same) whose credits are exhausted.
- Send any message in a Codex thread.
Expected behavior
The same treatment a Plus/Pro usage limit gets: the thread says Codex is out of quota, who can fix it, and stays visibly parked as a limit rather than a failure. Once #9012 lands, plan limits show a labeled "Usage limit reached — limits reset …" notice; the Business equivalent is "Workspace is out of credits — ask your workspace owner to add credits", with no countdown (credits are refilled, not reset) and cleared the next time Codex reports credits.hasCredits: true.
Actual behavior
A generic red thread error banner carrying Codex's raw sentence. It is indistinguishable from a provider crash, so it reads as "something broke" rather than "you hit a limit", and there is nothing telling me the thread is waiting on the workspace owner.
Why, verified against source:
- Codex classifies all four workspace stops —
workspace_owner_credits_depleted,workspace_member_credits_depleted,workspace_owner_usage_limit_reached(spend cap),workspace_member_usage_limit_reached— asCodexErrorInfo::UsageLimitExceeded, the same error code as Plus/Pro limits (codex-rs/protocol/src/error.rs,to_codex_protocol_error). Only the message text differs. - Codex's
account/rateLimits/updatedsnapshot carries the structured facts:rateLimitReachedType,planType(business,enterprise,team, …),credits { hasCredits, balance, unlimited },spendControlReached. CodexAdapteronly treats the account as limited when a rate-limit window is at 100% and has aresetsAt. Credit depletion has neither, so the structured signal is dropped on the floor.- The failed
turn/completedthen stamps the message intosession.lastError(ProviderRuntimeIngestion.ts), which every client renders as the generic redThreadErrorBanner.
This is the Business-account sibling of #6513 (Claude) and of the plan-limit handling in #7165 / #9012. Business plan types were already a blind spot once (#8537, #8292).
Impact
Minor bug or occasional failure
Version or commit
main@70cd258d8 (also reproduced on the #7165 and #9012 branches)
Environment
Linux (Arch), web client against a local t3 server. Codex CLI signed in with a ChatGPT Business workspace account (credit-based billing).
Logs or stack traces
Shape of the exchange per the app-server protocol (schema, not a captured log):
error { error: { message: "Your workspace is out of credits. Ask your workspace owner to refill in order to continue.",
codexErrorInfo: "usageLimitExceeded" }, willRetry: false }
turn/completed { turn: { status: "failed", error: { message: "Your workspace is out of credits. …" } } }
account/rateLimits/updated { rateLimits: { planType: "business", rateLimitReachedType: "workspace_member_credits_depleted",
credits: { hasCredits: false, … } } }
Screenshots, recordings, or supporting files
Workaround
None inside T3 Code. The workspace owner adds credits, then the user starts a new turn.
Activity
vitalyiegorov commentedon Sep 3, 2026
Update after checking merged history: #8358 (Grok) established the accepted model for a usage-limit stop — fail the turn with a visible usage-limit message, session back to ready. Codex on
mainalready does that for workspace credit exhaustion (the banner carries Codex's own sentence), so this is consistent with the merged design rather than a defect. Closing; the remaining ask (a softer, limit-styled banner across providers) is a UX preference better suited to an Ideas discussion.