codex exec retries 401s instead of failing fast when no credentials are configured

Open 💬 1 comment Opened Jun 29, 2026 by MongLong0214

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/codex main at 6b5f574
  • Latest LazyCodex source checked: code-yeongyu/lazycodex main at d4c4f05
  • OS: macOS arm64
  • Install method: npm global Codex CLI
  • Relevant config: reproduction uses an empty temporary CODEX_HOME and --ignore-user-config

Repository Decision

  • Target repository: openai/codex
  • Why this belongs there: the failure reproduces through upstream codex exec with --ignore-user-config and an empty CODEX_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.rs enters the normal exec session path; codex-rs/login/src/auth/manager.rs can return None when no credentials are configured; codex-rs/model-provider/src/auth.rs maps missing auth to an unauthenticated auth provider with empty headers; codex-rs/core/src/responses_retry.rs then retries stream errors and falls back transport.

Reproduction

  1. Start from an environment with no auth environment overrides configured.
  2. Use a fresh empty Codex home:

``bash
export CODEX_HOME="$(mktemp -d)"
``

  1. Confirm local auth detection works:

``bash
codex login status
codex doctor --summary --ascii --no-color
``

  1. 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 20 seconds
  • 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 status with the empty home returned Not logged in and exit code 1.
  • codex doctor --summary --ascii --no-color with the empty home returned a local auth failure: no Codex credentials were found.
  • The same codex exec repro with --ignore-user-config still went to the network and retried 401s.
  • Runtime hypotheses checked:
  • Confirmed: codex exec lacks 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.rs returns None when no stored credentials or auth env vars are available.
  • codex-rs/model-provider/src/auth.rs converts None into UnauthenticatedAuthProvider, 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().await returns None
  • 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 status still reports authenticated homes correctly.
  • codex exec with a valid logged-in home still succeeds.
  • codex exec --oss or local provider paths still work without first-party auth.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗