+1
[Bug]: Usage Limits shows Codex -32600 warnings for custom proxy providers without OpenAI auth#11873
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
- Configure a Codex provider with a working CLIProxyAPI endpoint and a proxy API key supplied through ANTHROPIC_AUTH_TOKEN. Use launch arguments equivalent to:
| 1 | -c model_providers.cliproxy.name="cliproxy" |
| 2 | -c model_providers.cliproxy.base_url="http://PROXY:8317/v1" |
| 3 | -c model_providers.cliproxy.env_key="ANTHROPIC_AUTH_TOKEN" |
| 4 | -c model_providers.cliproxy.wire_api="responses" |
| 5 | -c model_provider="cliproxy" |
- Do not add a direct ChatGPT subscription login to this Codex environment.
- Open Usage > Limits in T3 Code. A warning appears for each affected environment.
- Optionally configure a CLIProxyAPI usage source. Its quota cards can be populated while the separate Codex warnings remain.
Expected behavior
Direct Codex subscription usage should be classified as unsupported for a custom provider without a subscription account. Independently configured CLIProxyAPI usage-source data should remain visible. Genuine failures for subscription-authenticated accounts should remain actionable.
Actual behavior
Both the desktop client and app.t3.codes display:
| 1 | Codex (via cliproxy): Codex could not read usage (JSON-RPC -32600). |
This occurs for three connected environments, while CLIProxyAPI usage-source quota cards are populated.
Impact
Minor bug or occasional failure
Persistent misleading warnings in Usage > Limits. No model-request failure was established by this investigation.
Version or commit
T3 server 0.0.40 on two Linux Kubernetes instances; T3 server 0.0.41-nightly.20260910.1473 on a Debian 13 server.
Environment
Linux; Debian 13 on the standalone server; Node v24.20.0 on that server; Codex CLI 0.154.0; custom CLIProxyAPI provider using Responses API and an environment-variable API key. Seen in both desktop and hosted web clients. Exact desktop version was not collected.
Logs or stack traces
Directly reproduced against codex app-server with the provider overrides above, after initialize and initialized:
| 1 | {"id":2,"method":"account/read","params":{"refreshToken":false}} |
| 2 | {"id":2,"result":{"account":null,"requiresOpenaiAuth":false}} |
| 3 | {"id":3,"method":"account/rateLimits/read","params":{}} |
| 4 | {"id":3,"error":{"code":-32600,"message":"codex account authentication required to read rate limits"}} |
Code inspection of the installed nightly server bundle: the Codex provider probe calls account/rateLimits/read and maps failures through codexRateLimitsFailureMessage. The usageLimits mapping classifies account.type === "apiKey" as unsupported, but account === null with requiresOpenaiAuth === false falls through to probeFailed. This is a suspected missing classification, not a tested patch.
Screenshots, recordings, or supporting files
No attachments. The exact warning and protocol reproduction are included above.
Workaround
No warning-removal workaround was applied. Independently configured CLIProxyAPI usage-source quota cards remain available. No runtime patch or authentication changes were made.
Report investigated and filed by an OpenCode agent using codex/gpt-6-astra. This was not run through t3 triage.
I'm also getting this (due to codex technically not being logged in) as it's going through CLIProxy
I traced this on current main, and the report's classification looks right.
probeCodexAppServerProvider already has the authoritative account result before it starts the parallel enrichment calls:
account === null && requiresOpenaiAuth === trueโ unauthenticated Codex, early return.account === null && requiresOpenaiAuth === falseโ custom provider that does not require a ChatGPT/OpenAI subscription account.
The second case currently falls through to account/rateLimits/read. Codex then returns the expected -32600 because there is no subscription account to read. checkCodexProviderStatus sees snapshot.rateLimits.failure and converts that expected absence into probeFailed, which is why the Limits UI shows an actionable-looking warning.
I think the narrow invariant should be:
| 1 | no subscription account + provider does not require OpenAI auth |
| 2 | => subscription limits are unsupported, not probe-failed |
The smallest fix could classify
| 1 | snapshot.account.account === null && |
| 2 | snapshot.account.requiresOpenaiAuth === false |
the same as the existing account.type === "apiKey" usage-limits case: makeUnavailableUsageLimits({ reason: "unsupported" }).
I'd also skip account/rateLimits/read in that state rather than intentionally issuing an RPC Codex says is invalid. Models and skills can still be probed normally.
Important boundary from #13053: this should key off the authoritative Codex account/read shape above, not a generic failed limits request. An actually subscribed account whose usage probe failed must remain probeFailed, because unsupported intentionally rejects later live window updates.
Focused regression I'd want:
account: null, requiresOpenaiAuth: falseโ provider stays ready, Usage Limits isunsupported, no rate-limit RPC/warning.account: null, requiresOpenaiAuth: trueโ existing unauthenticated path unchanged.- ChatGPT account + failed
account/rateLimits/readโ stillprobeFailed. - API-key account โ existing
unsupportedbehavior unchanged.
That keeps "known absence" separate from "measurement failed" without changing the limits contract.
Independent reproduction on a newer Codex CLI, plus evidence that the existing unsupported classification is already reachable โ only the detection is missing.
Environment: T3 Code 0.0.46-nightly.20261003.2610 (Omarchy/Arch, x86_64), codex-cli 0.160.0. Codex pointed at a CLIProxyAPI endpoint through a custom model_providers entry (wire_api = "responses", key via env_key), with no auth.json present.
Protocol transcript (fresh codex app-server over stdio, using T3's exact initialize params):
| 1 | {"id":2,"method":"account/read","params":{}} |
| 2 | {"id":2,"result":{"account":null,"requiresOpenaiAuth":false,"workspaceRouting":null}} |
| 3 | {"id":3,"method":"account/rateLimits/read","params":null} |
| 4 | {"id":3,"error":{"code":-32600,"message":"codex account authentication required to read rate limits"}} |
params: {} produces the identical -32600. Worth noting for anyone reading the UI text: params: null is legal in codex 0.160.0's own generated schema (anyOf: [GetAccountRateLimitsParams, null]), so this is not a schema violation. Codex uses -32600 as a catch-all for "no subscription account", which is why codexRateLimitsFailureMessage renders an expected absence as a JSON-RPC protocol failure.
Still present on current builds. The three lines that decide this are unchanged in 0.0.42, 0.0.44, 0.0.45 and 0.0.46-nightly.20261003.2610 / .2623 / .2632:
- the early return gated on
!accountResponse.account && accountResponse.requiresOpenaiAuth; snapshot.account.account?.type === "apiKey"โmakeUnavailableUsageLimits({ reason: "unsupported" });- the unconditional
client.request("account/rateLimits/read", null).
So upgrading does not clear the warning.
The apiKey classification is reachable โ only the detection is missing. Giving the same CODEX_HOME a stored api-key account (verified in a throwaway CODEX_HOME; the real one was left untouched):
| 1 | echo "$KEY" | CODEX_HOME=/tmp/codexhome-probe codex login --with-api-key |
| 2 | |
| 3 | {"id":2,"method":"account/read"} -> {"account":{"type":"apiKey"},"requiresOpenaiAuth":true} |
T3 then takes the existing account.type === "apiKey" path, and Limits correctly reports "unsupported" with no warning. codex login does not validate the key, and it does not change request routing because the custom model_provider still supplies base_url / env_key.
I want to be explicit that this is diagnostic evidence for the classification gap, not a workaround worth shipping โ it writes a credential file purely to change which probe branch runs, and it only works because account.type === "apiKey" already happens to be classified correctly.
There is no user-side mitigation. skipNativeUsage is only set when T3 supplies managed ChatGPT auth, and the Codex provider settings schema exposes just enabled, binaryPath, homePath, launchArgs and customModels. Affected users cannot turn the probe off from the UI.
This supports @kvnloo's read: account === null && requiresOpenaiAuth === false is a known absence, not a failed measurement, and should map to makeUnavailableUsageLimits({ reason: "unsupported" }) while skipping the account/rateLimits/read call entirely. The extra data point here is that the unsupported path is already proven to render correctly for this exact account state, so the fix is purely about reaching it.
Still reproduces on 0.0.46-nightly.20261011.2955 with Codex CLI 0.162.1. It also happens with a different provider auth setup than the original report: a [model_providers.<id>.auth] command in config.toml that prints the proxy key, rather than env_key.
Same protocol result against codex app-server, which now also returns workspaceRouting:
| 1 | account/read โ {"account":null,"requiresOpenaiAuth":false,"workspaceRouting":null} |
| 2 | account/rateLimits/read โ {"code":-32600,"message":"codex account authentication required to read rate limits"} |
In the current server bundle, probeCodexAppServerProvider still returns early only for account === null && requiresOpenaiAuth === true. The false case falls through to account/rateLimits/read, unless skipNativeUsage is set, and that only happens for managed auth. The warning shows on every environment that routes Codex through a proxy, even when a CLIProxyAPI usage source already reports those Codex windows. So +1 to the classification @kvnloo described: treat account: null with requiresOpenaiAuth: false as unsupported, and skip the RPC.
Investigated by Claude Opus 5.5, an AI agent running in Claude Code, on behalf of a user.
Still reproduces on T3 Code desktop 0.1.1-nightly.20261020.3411, connected to an Omarchy environment running codex-cli 0.163.0 through an OmniRoute wrapper configured as a separate Codex provider with its own home directory.
Opening Usage โ Limits shows:
| 1 | Free AI via Codex: Codex could not read usage (JSON-RPC -32600). |
Direct requests to the wrapper's codex app-server, after the initialize/initialized handshake, confirm:
| 1 | account/read โ {"account":null,"requiresOpenaiAuth":false} |
| 2 | account/rateLimits/read โ {"code":-32600,"message":"codex account authentication required to read rate limits"} |
As a control, account/rateLimits/read succeeds for the regular ChatGPT-authenticated Codex installation on the same environment.
This adds an OmniRoute reproduction on Codex 0.163.0. The expected behavior is the same as described above: classify this account state as unsupported and skip the subscription usage probe, while preserving warnings for genuine failures on subscription-authenticated accounts.
No authentication changes or runtime patches were applied. No fix has been tested.
Reproduced on main 3b95e7831b with codex-cli 0.163.0 on Ubuntu 24.04. The real web dev app shows the exact JSON-RPC -32600 warning in Usage โ Limits with an empty Codex home and the reported custom-provider launch arguments. A fixture API key suffices: account/read reports account=null and requiresOpenaiAuth=false; the subscription rate-limit RPC fails before contacting the proxy.
Still reproducible with T3 v0.1.2 and codex-cli 0.165.0 on Linux. An independently configured CLIProxyAPI usage source returns quota data successfully while the separate Codex provider shows Codex could not read usage (JSON-RPC -32600).
I also reproduced the underlying RPC response with a temporary, empty CODEX_HOME, no auth.json, and this synthetic configuration:
| 1 | model_provider = "custom" |
| 2 | |
| 3 | [model_providers.custom] |
| 4 | name = "Custom API" |
| 5 | base_url = "http://127.0.0.1:1/v1" |
| 6 | wire_api = "responses" |
| 7 | requires_openai_auth = false |
| 8 | env_key = "CUSTOM_API_KEY" |
With CUSTOM_API_KEY=synthetic-placeholder, start codex app-server, complete initialize / initialized, then send:
| 1 | {"id":2,"method":"account/read","params":{}} |
| 2 | {"id":2,"result":{"account":null,"requiresOpenaiAuth":false,"workspaceRouting":null}} |
| 3 | {"id":3,"method":"account/rateLimits/read","params":null} |
| 4 | {"id":3,"error":{"code":-32600,"message":"codex account authentication required to read rate limits"}} |
No working proxy or real credential is needed for this RPC reproduction. This isolates the native subscription-limit probe from the separately configured usage source.
Source inspection of main at 2b15ba077d8ee756c01dbf44d959068ef03e371d still shows the same gap in CodexProvider.ts: the no-account/auth-optional state proceeds to account/rateLimits/read, and only API-key accounts are classified as unsupported; this response becomes probeFailed.
This supports the existing report and maintainer-owned #18622. No fix, rebuilt UI, or Windows-specific runtime behavior was tested; the standalone reproduction above was on Linux. No authentication changes or runtime patches were applied to the installed app.
Additional reproduction on T3 Code Nightly 0.1.6-nightly.20261031.3977, Codex CLI 0.166.0, macOS 27.2 / Apple Silicon.
The enabled Codex instance routes requests through CLIProxy using a custom model_provider=cliproxy, a local Responses API endpoint, and an environment-variable API key. CLI Proxy Hub already displays usage correctly, but T3 Code's Usage page still shows:
| 1 | Codex: Codex could not read usage (JSON-RPC -32600). |
A standalone codex app-server launched with the same provider overrides, after the initialize / initialized handshake, returned:
| 1 | account/read |
| 2 | โ {"account":null,"requiresOpenaiAuth":false,"workspaceRouting":null} |
| 3 | |
| 4 | account/rateLimits/read |
| 5 | โ {"code":-32600,"message":"codex account authentication required to read rate limits"} |
| 6 | |
| 7 | account/usage/read |
| 8 | โ {"code":-32600,"message":"codex account authentication required to read token usage"} |
As a control, the normal ChatGPT-authenticated Codex installation on the same machine successfully returned rate limits and token usage without the custom-provider overrides.
This confirms the existing report on a newer nightly and Codex version, and shows that the token-usage RPC has the same authentication requirement. The UI exposes the numeric code without the explanatory message, making this expected absence of a native subscription account look like a failure.
Expected behavior: treat the authoritative account: null, requiresOpenaiAuth: false state as unsupported native subscription usage, skipping those RPCs and either omitting the native warning or showing a neutral explanation. Independently configured hub usage should remain available; genuine usage-probe failures for ChatGPT-authenticated accounts should retain their warnings.
Investigated and reported with Codex on behalf of the user. No authentication changes or runtime patches were applied.
Reproduced on T3 Code 0.1.6, after updating both the macOS desktop app and its connected Linux ARM64 backend. The warning was also visible on 0.1.5. A new screenshot on 2026-10-31 shows that it persists with Usage > Limits > All environments > All providers selected.
The affected remote environment reports:
| 1 | Codex: Codex could not read usage (JSON-RPC -32600). |
A fresh probe used the running 0.1.6 backend's Codex executable, launch environment and configured home. With Codex CLI 0.166.0:
- Initialization succeeds.
account/readsucceeds withaccount: nullandrequiresOpenaiAuth: false.account/rateLimits/readfails with-32600and an error containing the phrasechatgpt authentication required.- Both
params: nullandparams: {}produce that authentication requirement.
The v0.1.6 source still makes the native quota request in this state: provider discovery. Its unsupported-limit classification only explicitly handles an apiKey account, so the observed null-account state becomes probeFailed.
This matches the missing-classification concern in the original report. I have not established that this environment uses the same CLIProxyAPI configuration, or that model requests fail. The tested request formats do not support changing null to an empty object as the fix.
Expected behavior: skip unsupported native ChatGPT quota polling for this account mode, keep supported usage sources available, and retain meaningful errors for actual ChatGPT quota failures.
A temporary display workaround is to exclude the affected remote environment using All environments, retaining an environment that reports limits successfully. The environment/provider filtering code filters its entries and warnings together. This does not repair the underlying polling behavior. Excluding Codex in the provider filter also hides its warnings, but removes successful Codex limit cards from that view too.
No active runtime patch was installed, no provider/authentication settings were changed, and no existing chat processes were restarted. The reproduction was investigated through t3 triage --agent codex in read-only mode. The CLI used its configured default model and did not report the exact model identifier.
Still reproducible on T3 Code 0.1.7-nightly.20261102.4066 (Linux x64, Rocky Linux 9.8, a RHEL 9 rebuild, background service), codex-cli 0.166.0, CLIProxyAPI 8.0.44.
Setup: ~/.codex/config.toml has model_provider = "cliproxy" with requires_openai_auth = false pointing at a local Responses endpoint, and no ChatGPT login in ~/.codex. A cliproxy usage limit source on the same host returns the Codex account's quota correctly.
Usage โ Limits shows: <env label> ยท Codex: Codex could not read usage (JSON-RPC -32600). The thread details card shows Limits: Unavailable for the same instance.
Replaying the probe against codex app-server on the same machine, after initialize / initialized:
account/readโ{"account":null,"requiresOpenaiAuth":false,"workspaceRouting":null}account/rateLimits/readโ-32600 "codex account authentication required to read rate limits"
probeCodexAppServer only skips the rate-limit read when requiresOpenaiAuth is true (apps/server/src/provider/CodexProvider.ts:543), so a custom provider without a login ends up as probeFailed and the banner.
Triage by Claude Code (claude-fable-5-1) via t3 triage.
Additional reproduction with DeepSeek configured as the model provider using DeepSeek's official Codex integration. This does not use CLIProxyAPI.
Environment
- T3 Code
0.1.7 - Codex CLI
0.166.0 - Linux x86_64
- Provider:
Codex (DeepSeek), statusready - Config:
model_provider = "deepseek"andforced_login_method = "api", following the DeepSeek Codex integration guide - No ChatGPT/OpenAI subscription account is present in this Codex home
Actual behavior
Usage โ Limits shows:
| 1 | Codex (DeepSeek): Codex could not read usage (JSON-RPC -32600). |
A fresh codex app-server probe using this Codex home, after initialize and initialized, returns:
| 1 | {"id":2,"result":{"account":null,"requiresOpenaiAuth":false,"workspaceRouting":null}} |
| 2 | {"error":{"code":-32600,"message":"codex account authentication required to read rate limits"},"id":3} |
T3 caches this as usageLimits.unavailable.reason = "probeFailed" even though account/read has already established that this provider does not require OpenAI authentication. The provider remains ready and model requests are unaffected.
Expected behavior
Treat account: null with requiresOpenaiAuth: false as a known unsupported native subscription-limit state, skip account/rateLimits/read, and do not surface a warning. Keep probeFailed for actual failures when a ChatGPT-authenticated account should be able to read limits.
This confirms that the defect is not specific to proxy providers and reproduces with DeepSeek's documented first-party Codex setup. It appears to be the same classification gap already proposed for fixing in the discussion above and #18622.
Note
๐ค Claude Opus 5.5 responding on behalf of amanthanvi
There's a related case that #22772 doesn't cover: the custom-provider Codex home also holds a ChatGPT login.
- Stale login: the account-less check in #22772 doesn't apply, and the usage read fails with a different code. Usage โ Limits shows
Codex could not read usage (JSON-RPC -32603).The home'sauth.jsonis inchatgptmode, with tokens last refreshed about six weeks ago.- Observed on T3
0.1.8-nightly.20261106.4247with codex-cli0.167.0on Linux. - The instance runs with
-c model_provider=<proxy>launch overrides against a CLIProxyAPI gateway. - Inference: -32603 is Codex failing to refresh the expired ChatGPT tokens, not the account-less refusal.
- Observed on T3
- Valid login: the read succeeds, so the proxy-routed instance shows that ChatGPT account's own subscription windows. That's misleading, because the instance's traffic goes through the proxy pool. The
cliproxyusage source already reports the pool's limits separately; this is the misattribution side of #23054.
A suggestion (my judgment, not verified against T3's code paths): decide from the effective model_provider rather than from the account shape. T3 already reads config/read during the same probe. When the provider isn't the built-in OpenAI one, skip account/rateLimits/read, as skipNativeUsage already does for managed ChatGPT instances, and report unsupported. That covers the account-less, stale-login and valid-login cases alike.
Still reproduces on T3 Code server 0.1.8-nightly.20261108.4367, Codex CLI 0.169.0-alpha.3, and CLIProxyAPI 8.0.61 on WSL2/Linux x86_64.
My Codex instance uses a custom Responses provider (model_provider = "cliproxy", wire_api = "responses", and an API key supplied through env_key). Its separate shadow home has no direct ChatGPT subscription login. The proxy has two active Codex accounts, and this conversation runs through the pool.
Usage shows:
| 1 | Codex pool: Codex could not read usage (JSON-RPC -32600) |
A fresh read-only codex app-server probe through the same pool wrapper, after initialize and initialized, returned these relevant fields:
| 1 | // account/read result |
| 2 | {"account": null, "requiresOpenaiAuth": false} |
| 3 | |
| 4 | // account/rateLimits/read, params: null |
| 5 | {"code": -32600, "message": "codex account authentication required to read rate limits"} |
The installed server still attempts the native quota RPC for this account state. Its usage classification explicitly handles account.type === "apiKey" as unsupported, but the null-account/custom-provider case becomes probeFailed.
In isolated checks against the extracted decision branches from the installed server, a candidate change skipped the native quota request for non-ChatGPT accounts and classified account === null && requiresOpenaiAuth === false as unsupported native usage. Those checks passed, including checks that ChatGPT quota failures remain failures. This was not a T3 source build or application-level regression test. I have not tested #18622 or #22772.
Expected: no native subscription-usage warning for this account mode; keep the separately configured CLIProxyAPI usage source available and retain genuine ChatGPT quota errors. No runtime patch or persistent authentication/settings changes were applied.