Custom provider HTTP 500 errors are mislabeled as OpenAI high demand

Open 💬 2 comments Opened Jul 13, 2026 by HarzerHeribert

What version of Codex CLI is running?

codex-cli 0.144.3

Platform

macOS arm64

What issue are you seeing?

When a custom OpenAI-compatible Responses provider returns HTTP 500, Codex discards the provider error details and displays:

We are currently experiencing high demand, which may cause temporary errors.

That message attributes an arbitrary custom-provider failure to service demand. A custom provider can use HTTP 500 for many unrelated conditions, so the message is misleading and hides the diagnostic information needed to fix the provider or request.

Minimal reproduction

  1. Configure a custom provider with wire_api = "responses" and an HTTP base URL.
  2. Have the fixture endpoint return:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json

{"error":{"code":"fixture_failure","message":"fixture-specific failure"}}
  1. Send any Codex prompt through that provider.
  2. Observe that Codex reports generic high demand rather than the HTTP status or fixture error.

Expected behavior

For custom providers, Codex should preserve a bounded provider error message, for example:

Custom provider returned HTTP 500: fixture-specific failure

The OpenAI-specific high-demand wording should be reserved for an explicit overload/capacity error code, not every HTTP 500.

Source-level cause

In codex-rs/codex-api/src/api_bridge.rs, TransportError::Http maps every StatusCode::INTERNAL_SERVER_ERROR directly to CodexErr::InternalServerError. In codex-rs/protocol/src/error.rs, that variant has the fixed high-demand display text. The HTTP body is therefore discarded for this status.

A safer mapping would retain the bounded response body for custom providers, or use the generic UnexpectedStatus representation unless an explicit overload code is present.

Additional information

This is the general form of the behavior previously reported for another custom backend in #2445, but it remains reproducible in CLI 0.144.3. This report intentionally uses only a synthetic fixture and contains no private provider details.

View original on GitHub ↗

2 Comments

tingxiao88 · 1 month ago

I've implemented and verified a fix for this, available here if the team wants to invite a PR (creating one directly is blocked for external accounts):

Branch: https://github.com/tingxiao88/codex/tree/fix-custom-provider-500-mislabeled
Diff: https://github.com/openai/codex/compare/main...tingxiao88:codex:fix-custom-provider-500-mislabeled

Approach: CodexErr::InternalServerError now carries message: Option<String>. The 500 branch in api_bridge.rs extracts the JSON error.message from the body (mirroring how the neighboring 503/400/429 branches parse theirs), so the CLI shows:

Model provider returned HTTP 500 Internal Server Error: fixture-specific failure

Explicit overload codes (server_is_overloaded/slow_down) and bodyless/non-JSON 500s keep the existing high-demand message, and the display is bounded by ERROR_MESSAGE_UI_MAX_BYTES.

I deliberately did not reroute 500s to UnexpectedStatus: that variant maps to CodexErrorInfo::Other, and the guardian review retry loop retries InternalServerError but not Other — a reroute would silently change guardian retry behavior. Keeping the variant means retryability, guardian retry, compaction model fallback, and analytics classification are all unchanged; only the message improves.

Verified with 4 new unit tests in api_bridge_tests.rs (all 15 map_api_error tests pass, clippy clean) and end-to-end against a local fixture returning 500 {"error":{"code":"fixture_failure","message":"fixture-specific failure"}} through a wire_api = "responses" custom provider — before: the high-demand message; after: the provider's actual error.

Happy to submit this as a PR if invited.

pcordon · 10 days ago

Same issue, with almost any OpenRouter model.