Skip to content

OpenRouter Ox Alpha returns HTTP 200 but Codex App receives an empty completion without retry #2423

Description

@optimikelabs

Client or integration

Codex App

Provider or upstream service

OpenRouter

OpenCodex version

2.31.0 (also reproduced after a controlled rollback to 2.29.0)

Endpoint or capability

POST /v1/responses, streaming, through the openai-chat adapter

Current behaviour

When Codex App sends a turn to openrouter/stealth-ox-alpha, OpenCodex routes it correctly and records HTTP 200, but Codex receives no assistant text, no tool call, no visible error, and no usage. The turn silently ends after roughly 4–8 seconds.

The request log records only one upstream send (sendCount: 1) and no recovery (recoveryKinds: []). Therefore the empty-completion guard introduced in #1655 does not retry this response shape and does not surface empty_completion_retry_failed.

The same symptom occurs with OpenCodex 2.29.0 and 2.31.0.

A direct request to the same OpenRouter model, with the same reasoning effort, succeeds outside OpenCodex:

  • non-streaming: HTTP 200, visible text and reasoning, usage returned;
  • streaming: HTTP 200, content deltas, reasoning deltas, usage and [DONE] returned.

This indicates that authentication, model availability, and the OpenRouter key are working.

Expected behaviour

OpenCodex should forward the model's visible output to Codex App. If the adapter actually produces a completed turn containing neither text nor a tool call, the guard from #1655 should retry the identical turn once and then either return content or surface empty_completion_retry_failed.

Minimal redacted request or reproduction

# Configure an OpenRouter provider with a valid key (not shown), then expose:
# provider: openrouter
# model: stealth/ox-alpha
# contextWindow: 1048576
# input modalities: text, image
# reasoning efforts: low, high, max
# default effort: max
# emptyCompletionRetry: true

ocx start --port 10100

# In Codex App, select openrouter/stealth-ox-alpha and send a simple prompt,
# for example: "Reply with exactly: test ok"

# Observed: the Codex turn ends without any assistant response.

Actual response or error

requestId: ocx-mt529pwy-j
provider: openrouter
model: stealth/ox-alpha
adapter: openai-chat
status: 200
durationMs: 7406
usageStatus: unreported
requestedEffort: max
effectiveEffort: max
reasoningWireField: reasoning_effort
reasoningWireValue: max
attempts[0].status: 200
attempts[0].durationMs: 4616
attempts[0].sendCount: 1
attempts[0].recoveryKinds: []
routeKind: explicit-provider

Codex App displays no assistant message and no error.

Upstream documentation

https://openrouter.ai/stealth/ox-alpha

OpenRouter uses the OpenAI-compatible chat completions API:
https://openrouter.ai/docs/api-reference/chat-completion

Suggested mapping or implementation notes

This looks like a response-shape coverage gap in the empty-completion guard from #1655. Possible areas to inspect:

  1. Whether the OpenRouter/Ox Alpha stream ends in a shape that the openai-chat adapter treats as a clean terminal/EOF but guardEmptyCompletionEventStream does not classify as an empty completed turn.
  2. Whether an Ox Alpha delta is classified as content by the guard but later discarded before reaching Codex App.
  3. The truncated-source branch: if the source ends without the exact terminal event expected by the guard, it may release held events and return without performing the configured retry.

The request log is especially relevant: a genuine empty-completion recovery should show a second send and an empty-completion recovery kind, but neither is present.

Additional context and attachments

Related work/issues:

Checks performed:

  • Existing provider and compatibility issues were searched; no issue specific to Ox Alpha was found.
  • The request and response details above are redacted and contain no credentials.
  • Direct OpenRouter tests confirmed that the upstream model returns visible output and usage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-infoWaiting on reporter for a concrete spec or reproductionproviderProvider adapters, OpenAI-compat presets, upstream API quirksprovider-compatibilityProvider compatibility reportstoolstool_calls, MCP, web-search / sidecar tools

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions