Allow custom model providers to disable automatic 401 auth recovery and replay

Open 💬 1 comment Opened Jul 26, 2026 by sswxiailongxia

What variant of Codex are you using?

Codex CLI and Codex App (provider transport shared in codex-rs)

What feature would you like to see?

Summary

Custom model providers can set requires_openai_auth = true and can independently
configure normal request and stream retry budgets. There is currently no provider
setting that disables the separate recovery-and-replay path entered after an HTTP
401 Unauthorized.

Please add an optional provider setting:

[model_providers.example]
name = "Example"
base_url = "https://example.invalid/v1"
wire_api = "responses"
requires_openai_auth = true
request_max_retries = 0
stream_max_retries = 0
auth_recovery_max_retries = 0

Expected behavior

  • When auth_recovery_max_retries is absent, preserve the current behavior.
  • When it is 0, the first 401 must be returned through the existing provider

error mapping without refreshing/reloading authentication and without replaying
the logical provider request.

  • When it is a positive integer N, allow at most N 401-triggered recovery and

replay cycles for that logical provider invocation.

  • Keep this budget independent from request_max_retries and

stream_max_retries.

  • Apply the same rule to Responses HTTP and WebSocket connection paths.

Why this is needed

On both the released source corresponding to 0.146.0-alpha.3.1 and the checked
main snapshot, a 401 enters handle_unauthorized(...) and a successful recovery
continues the surrounding loop, causing another provider request. Setting the
existing request and stream retry budgets to zero does not configure that separate
path.

Minimal acceptance tests

  1. Explicit zero + first HTTP request returns 401: one provider request, zero auth

recovery calls, no replay, original mapped 401 returned.

  1. Explicit zero + WebSocket connection returns 401: one connection attempt, zero

auth recovery calls, no reconnect caused by auth recovery.

  1. Positive budget of one: at most one recovery and one replay; a second 401 does

not cause a third provider request.

  1. Key absent: existing behavior remains unchanged.
  2. Invalid TOML values are rejected by the existing typed configuration/schema

path.

Scope

This request does not change endpoints, credential sources, token audiences,
fallback routing, the built-in OpenAI provider defaults, or telemetry schemas.

Verified source anchors

  • Release:

rust-v0.146.0-alpha.3.1,
commit
ff75c5b939c477c49eb1bd5248da6dab71b109d1

  • Checked main snapshot:

61a44880a85d2fd0d8770908dea5733495e571c8

  • Provider configuration:

codex-rs/model-provider-info/src/lib.rs

  • 401 recovery and replay:

codex-rs/core/src/client.rs

Additional information

A fuller local design proposal is attached for context. It is deliberately broader than this Issue; the requested implementation scope remains limited to the provider-scoped 401 recovery/replay budget described above.

Local proposal SHA-256: 3291ba284d98f8545f95b783e9636a57696f57fb9728fc063ecb2ebd1c01083e

OPENAI_CODEX_AUTH_RECOVERY_OTEL_UPSTREAM_PROPOSAL_CANDIDATE_V0.1.md

View original on GitHub ↗

1 Comment

Keesan12 · 1 month ago

Agree that auth recovery is a distinct retry budget. It is also a replay boundary: a single logical provider invocation can fan out into multiple physical requests through transport retry, stream retry, and 401 recovery. The receipt should show one logical invocation ID, every physical attempt, the trigger for each replay, and the remaining budget. auth_recovery_max_retries = 0 then becomes auditable, not just configurable.

If you add the setting, run the acceptance case through MartinLoop and send the receipt so we can verify there was exactly one provider attempt: https://github.com/Keesan12/martin-loop