Skip to content

fix(codex-cli): compatible-provider sessions use default OpenAI routing and lose the upstream error #681

Description

@Raymond8196

Description

Codex CLI sessions using hosted or compatible-provider credentials can use
stale/default OpenAI routing instead of the selected upstream.

When the upstream fails, the same logical failure may also be rendered multiple
times, or without the structured upstream error body — including cases where the
CLI wrote the reason to stderr but nothing is shown, and cases where a non-fatal
notice (Model metadata for ... Defaulting to fallback metadata) is reported as
the failure reason. API-key accounts can be misclassified into the native OAuth
refresh path.

ZenMux should use its Responses-compatible route. Providers that are not
verified end to end against the Codex Responses protocol — AtlasCloud, DeepSeek,
Groq, xAI, DashScope, Moonshot, LongCat, vLLM, Azure OpenAI and OpenRouter —
should be rejected before launch with a clear compatibility error rather than
failing at request time.

Steps to Reproduce

  1. Add a ZenMux API-key account and select it for a Codex CLI session.
  2. Select a namespaced model such as z-ai/glm-5.2.
  3. Send a prompt.
  4. Inspect the profile the session generated — $CODEX_HOME/config.toml — and
    the rendered terminal state. That profile is the single source of truth for
    routing: model_provider, base_url, wire_api, supports_websockets.
  5. Repeat with an invalid/expired credential or an unavailable model.
  6. Start two Codex sessions concurrently on different accounts and compare each
    session's config.toml.
  7. Optionally select a DeepSeek or AtlasCloud account for Codex and start a
    session.

Expected Behavior

  • ZenMux requests use the configured Responses base URL, model namespace, and
    HTTP/SSE transport (wire_api = "responses", supports_websockets = false),
    with no second endpoint override left in the child's environment.
  • Providers not registered as Responses-compatible fail before Codex starts,
    with a compatibility error naming the provider.
  • API-key accounts never enter native OAuth refresh bookkeeping.
  • Hosted sessions use isolated, session-scoped managed profiles that
    housekeeping later evicts; concurrent sessions never share one config.toml.
  • Retries are bounded: request_max_retries = 2 and stream_max_retries = 2 in
    the generated profile.
  • One logical terminal failure produces exactly one visible error carrying the
    authoritative upstream error body; non-fatal notices are never promoted into
    it.

Actual Behavior

  • Codex can fall back to wss://api.openai.com/v1/responses.
  • Connection/authentication errors can be retried or displayed repeatedly.
  • The rendered error can be blank even when the CLI emitted structured details,
    or wrote the reason to stderr.
  • A non-fatal Defaulting to fallback metadata notice can be reported as the
    failure reason.
  • API-key failures can be treated as OAuth failures.
  • Shared/stale hosted configuration can affect later sessions.

Environment

  • ORGII: 1.2.3
  • Codex CLI: 0.146.0 (first observed on 0.145.x)
  • OS: Ubuntu 22.04.5 LTS (kernel 6.8.0-134-generic)

Logs / Screenshots

Observed repeated connection/authentication failures targeting the default
OpenAI Responses WebSocket. Credentials and request identifiers must be redacted
before attaching logs.

Additional Context

Acceptance criteria:

  • Central compatibility registry controls Codex provider eligibility, enforced
    before launch and not only in the account picker.
  • Compatible profiles require an explicit model and a valid base URL; either one
    missing fails the launch instead of falling back.
  • Hosted Codex profiles are session-scoped and cleaned up.
  • Native OAuth retry is limited to matching native OAuth credentials.
  • Request and stream retries remain bounded (2 / 2).
  • Parser, transport, persistence, and UI agree on one authoritative terminal
    error.

Known trade-off — Codex's compatible_api_providers currently lists twelve
providers. Narrowing it to openai_api and zenmux_api moves the other ten —
atlascloud_api, openrouter_api, azure_openai_api, deepseek_api,
groq_api, xai_api, dashscope_api, moonshot_api, longcat_api,
vllm_api — from selectable but failing at request time to not selectable
on Codex. They remain available on the other agents. An upfront rejection beats
a session that dies mid-request, but this is a visible capability reduction for
anyone who currently has one of them selected.

The allowlist reflects verified, not possible. Azure OpenAI and OpenRouter
in particular are likely to speak the Responses API; they are excluded because
nobody has run a Codex session against them end to end, not because they are
known to be incompatible. Each one can be added back by a one-line registry
change once a session is confirmed working, and that is the preferred path over
re-widening the list wholesale.

Related hardening expected alongside the fix: credential staging files are
created 0600 rather than created under the process umask and chmod'd
afterwards, which leaves a group-readable window.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions