OAuth fallback silently uses hardcoded "dummy" API key after network change, causing 401
Bug Description
When using Codex CLI with ChatGPT OAuth authentication (preferred_auth_method = "chatgpt"), switching networks (e.g., WiFi → mobile hotspot, VPN toggle) causes the OAuth token to expire. Instead of prompting the user to re-authenticate, Codex silently falls back to a hardcoded "dummy" API key and sends it to the OpenAI API, resulting in:
[System Error] unexpected status 401 Unauthorized: Incorrect API key provided: dummy.
This affects both interactive Codex sessions and codex exec, as well as any third-party tool that spawns codex app-server.
Steps to Reproduce
- Log in via
codex loginusing ChatGPT OAuth - Start a Codex session, confirm it works
- Switch to a different network (different WiFi, VPN, hotspot, etc.)
- Continue or resume the session — or simply run
codex exec "say hello" - Codex sends requests with
"dummy"as the API key → 401
Reproduction Log
$ codex exec "say hello"
OpenAI Codex v0.145.0
provider: openai
model: gpt-5.6-sol
ERROR codex_api::endpoint::responses_websocket: failed to connect to websocket: HTTP error: 401 Unauthorized, url: wss://api.openai.com/v1/responses
ERROR: Reconnecting... 1/5
...
ERROR: Reconnecting... 5/5
warning: Falling back from WebSockets to HTTPS transport. unexpected status 401 Unauthorized: Incorrect API key provided: dummy. You can find your API key at https://platform.openai.com/account/api-keys., url: wss://api.openai.com/v1/responses
Expected Behavior
When the OAuth token cannot be refreshed, Codex should prompt the user to re-authenticate, not silently fall back to a dummy key.
Actual Behavior
Codex falls back through this chain:
- Try OAuth token refresh → fails (network changed, session stale)
- Try keychain → encryption key present but OAuth credentials stale
- Try
~/.codex/auth.json→ contains{"auth_mode": "apikey", "OPENAI_API_KEY": "dummy"} - If
auth.jsonis deleted → binary has hardcoded"dummy"as ultimate fallback - Request sent with
Authorization: Bearer dummy→ 401
What I've Tried
- Deleting
~/.codex/auth.json— Codex uses hardcoded"dummy"fallback in the binary - Setting
cli_auth_credentials_store = "keyring"inconfig.toml— dummy still used - Only
codex logout && codex loginresolves the issue, but must be done after every network change
Environment
- macOS 15 (Darwin 24.2.0, arm64)
- Codex CLI v0.145.0 (installed via Homebrew)
preferred_auth_method = "chatgpt"in~/.codex/config.toml
Related Issues
- #20871 — auth.json not reliably updated by
codex login - #15151 — silent fallback causing misleading 401
- #31459 — revoked OAuth token still used after logout/login
- #5212 — OPENAI_API_KEY vs auth.json handling
Suggested Fix
When all auth methods fail, Codex should surface a clear error like "OAuth session expired. Run codex login to re-authenticate." instead of silently using "dummy" as the API key.
4 Comments
Thanks for the detailed report. Could you confirm whether ~/.codex/auth.json is regenerated after a logout/login cycle in this failure path, and whether codex config still shows preferred_auth_method as chatgpt after the network switch? A single debug run with CODEX_LOG=debug and one codex exec "say hello" (with secrets redacted) would help confirm whether the final fallback happens before or after token refresh failure. Please include your exact macOS build channel and version if possible.
Could you share the exact value of
OPENAI_API_KEYin your environment when this happens, and whether~/.codex/auth.jsonis regenerated if you runcodex logoutthencodex loginwithout network changes? I can then suggest a minimal guard to avoid dummy-key fallback during network transitions.1.
OPENAI_API_KEYin environmentOPENAI_API_KEYis not set in the environment at the time of failure. No other OpenAI-related env vars are present either.2. Does
auth.jsonregenerate aftercodex logout && codex login?No. After logout/login (without network changes),
auth.jsonis not recreated. Credentials are stored only in the macOS Keychain under service"Codex Auth".3. Debug log
I’ve re-logged in and the issue isn’t currently reproducing. I’ll attach a full CODEX_LOG=debug log next time it occurs.
4. Environment
preferred_auth_method = "chatgpt"cli_auth_credentials_store = "keyring"(added while debugging, didn't help)OPENAI_API_KEYis unsetUpdate: Reproduced the failure and captured
RUST_LOG=debugoutput. The auth flow reveals two compounding issues:Successful run (before network change)
Failed run (after network change)
What's happening
After a network change, the models cache (300s TTL) expires and Codex needs to re-fetch from
chatgpt.com. The OAuth access token is likely expired and the refresh fails silently on the new network. At this point:auth_mode="Chatgpt"toauth_mode="ApiKey", substituting the hardcoded"dummy"as the API key. No error is shown to the user."ApiKey", concludes"not_chatgpt_auth", and skips token refresh entirely. The original ChatGPT OAuth context is lost, so recovery can never kick in.