codex exec retries 401s instead of failing fast when no credentials are configured
Summary
codex exec does not appear to fail fast when no credentials are configured. With an empty CODEX_HOME, codex login status and codex doctor both detect the missing credentials locally, but codex exec still opens the Responses transport, retries multiple 401s, falls back from WebSocket to HTTPS, and exits after about 20 seconds.
Environment
- LazyCodex version: 4.13.0, installed as an OMO plugin payload
- Codex version:
codex-cli 0.141.0 - Latest upstream source checked:
openai/codexmain at6b5f574 - Latest LazyCodex source checked:
code-yeongyu/lazycodexmain atd4c4f05 - OS: macOS arm64
- Install method: npm global Codex CLI
- Relevant config: reproduction uses an empty temporary
CODEX_HOMEand--ignore-user-config
Repository Decision
- Target repository:
openai/codex - Why this belongs there: the failure reproduces through upstream
codex execwith--ignore-user-configand an emptyCODEX_HOME, without LazyCodex config or plugin loading. - LazyCodex evidence: latest LazyCodex source only provides surrounding OMO doctor/reporting skills and does not own
codex exec, auth loading, or Responses transport retry behavior. - Upstream Codex source evidence:
codex-rs/exec/src/lib.rsenters the normal exec session path;codex-rs/login/src/auth/manager.rscan returnNonewhen no credentials are configured;codex-rs/model-provider/src/auth.rsmaps missing auth to an unauthenticated auth provider with empty headers;codex-rs/core/src/responses_retry.rsthen retries stream errors and falls back transport.
Reproduction
- Start from an environment with no auth environment overrides configured.
- Use a fresh empty Codex home:
``bash``
export CODEX_HOME="$(mktemp -d)"
- Confirm local auth detection works:
``bash``
codex login status
codex doctor --summary --ascii --no-color
- Run non-interactive exec through the same empty home:
``bash``
codex exec --ignore-user-config --sandbox read-only 'Reply exactly: SHOULD_NOT_RUN_WITHOUT_AUTH'
Expected Behavior
codex exec should fail before making Responses API calls, with a clear local error like Not logged in / Run codex login or provide an API key.
Actual Behavior
The command attempted the Responses transport without credentials. In the captured run:
- Exit code:
1 - Elapsed time: about
20seconds - WebSocket 401 count:
7 - Reconnect messages:
9 - Final HTTPS error included
401 Unauthorized: Missing bearer or basic authentication in header
Relevant stderr excerpt:
ERROR codex_api::endpoint::responses_websocket: failed to connect to websocket: HTTP error: 401 Unauthorized, url: wss://api.openai.com/v1/responses
ERROR: Reconnecting... 2/5
ERROR: Reconnecting... 3/5
ERROR: Reconnecting... 4/5
ERROR: Reconnecting... 5/5
warning: Falling back from WebSockets to HTTPS transport. unexpected status 401 Unauthorized: Missing bearer or basic authentication in header
ERROR: Reconnecting... 1/5
ERROR: Reconnecting... 2/5
ERROR: Reconnecting... 3/5
ERROR: Reconnecting... 4/5
ERROR: Reconnecting... 5/5
ERROR: unexpected status 401 Unauthorized: Missing bearer or basic authentication in header
Evidence
codex login statuswith the empty home returnedNot logged inand exit code1.codex doctor --summary --ascii --no-colorwith the empty home returned a local auth failure:no Codex credentials were found.- The same
codex execrepro with--ignore-user-configstill went to the network and retried 401s. - Runtime hypotheses checked:
- Confirmed:
codex execlacks an early local no-auth preflight for this path and falls through to provider transport. - Refuted: auth existed through env but was invalid; auth environment overrides were unset.
- Refuted: LazyCodex/plugin hooks caused the behavior; the repro used
--ignore-user-config, and the relevant source path is upstream Codex. - Existing issue search found related 401/auth issues, but not this empty-home no-credentials preflight case.
Root Cause
Strongly evidenced source path:
codex-rs/login/src/auth/manager.rsreturnsNonewhen no stored credentials or auth env vars are available.codex-rs/model-provider/src/auth.rsconvertsNoneintoUnauthenticatedAuthProvider, which intentionally emits no auth headers.- The first-party Responses request then receives 401 and is handled by the generic retry/fallback logic in
codex-rs/core/src/responses_retry.rs.
This is likely correct for local/OSS or custom providers that explicitly require no OpenAI auth, but it is noisy and slow for the default first-party codex exec path.
Proposed Fix
Add a fast preflight for first-party OpenAI/Codex providers in the codex exec startup or turn setup path:
- If the selected provider requires first-party auth and
AuthManager::auth().awaitreturnsNone - And there is no provider-level API key / external bearer credential
- Then return a local actionable error before opening WebSocket or HTTPS Responses transports.
The fix should not affect:
- OSS/local providers
- Custom providers configured with no OpenAI auth requirement
- Providers that supply auth through their own
env_key, bearer credential, or command-backed auth config
Verification Plan
- Reproduce before fix with empty
CODEX_HOME; observe delayed 401 retries. - After fix, run the same command and verify it exits immediately with a local auth message and no Responses API attempts.
- Regression check:
codex login statusstill reports authenticated homes correctly.codex execwith a valid logged-in home still succeeds.codex exec --ossor local provider paths still work without first-party auth.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗