[Bug]: Usage Limits shows Codex -32600 warnings for custom proxy providers without OpenAI auth#11873

openedSep 15, 2026bySSpyrosPsarras

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

  1. Configure a Codex provider with a working CLIProxyAPI endpoint and a proxy API key supplied through ANTHROPIC_AUTH_TOKEN. Use launch arguments equivalent to:
text
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"
  1. Do not add a direct ChatGPT subscription login to this Codex environment.
  2. Open Usage > Limits in T3 Code. A warning appears for each affected environment.
  3. 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:

text
1Codex (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:

json
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.

Synced from GitHub

I'm also getting this (due to codex technically not being logged in) as it's going through CLIProxy

Synced from GitHub

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:

1no subscription account + provider does not require OpenAI auth
2=> subscription limits are unsupported, not probe-failed

The smallest fix could classify

ts
1snapshot.account.account === null &&
2snapshot.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:

  1. account: null, requiresOpenaiAuth: false โ†’ provider stays ready, Usage Limits is unsupported, no rate-limit RPC/warning.
  2. account: null, requiresOpenaiAuth: true โ†’ existing unauthenticated path unchanged.
  3. ChatGPT account + failed account/rateLimits/read โ†’ still probeFailed.
  4. API-key account โ†’ existing unsupported behavior unchanged.

That keeps "known absence" separate from "measurement failed" without changing the limits contract.

Synced from GitHub

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):

json
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):

1echo "$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.

Synced from GitHub

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:

text
1account/read โ†’ {"account":null,"requiresOpenaiAuth":false,"workspaceRouting":null}
2account/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.

Synced from GitHub

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:

text
1Free 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:

text
1account/read โ†’ {"account":null,"requiresOpenaiAuth":false}
2account/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.

Synced from GitHub

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:

toml
1model_provider = "custom"
2
3[model_providers.custom]
4name = "Custom API"
5base_url = "http://127.0.0.1:1/v1"
6wire_api = "responses"
7requires_openai_auth = false
8env_key = "CUSTOM_API_KEY"

With CUSTOM_API_KEY=synthetic-placeholder, start codex app-server, complete initialize / initialized, then send:

json
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.

Synced from GitHub

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:

text
1Codex: 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:

text
1account/read
2 โ†’ {"account":null,"requiresOpenaiAuth":false,"workspaceRouting":null}
3
4account/rateLimits/read
5 โ†’ {"code":-32600,"message":"codex account authentication required to read rate limits"}
6
7account/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.

Synced from GitHub

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:

text
1Codex: 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/read succeeds with account: null and requiresOpenaiAuth: false.
  • account/rateLimits/read fails with -32600 and an error containing the phrase chatgpt authentication required.
  • Both params: null and params: {} 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.

Synced from GitHub

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.

Synced from GitHub

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), status ready
  • Config: model_provider = "deepseek" and forced_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:

text
1Codex (DeepSeek): Codex could not read usage (JSON-RPC -32600).

A fresh codex app-server probe using this Codex home, after initialize and initialized, returns:

json
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.

Synced from GitHub

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's auth.json is in chatgpt mode, with tokens last refreshed about six weeks ago.
    • Observed on T3 0.1.8-nightly.20261106.4247 with codex-cli 0.167.0 on 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.
  • 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 cliproxy usage 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.

Synced from GitHub

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:

text
1Codex 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:

json
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.