Skip to content

[Bug]: Responses-compatible gateways can return sparse lifecycle snapshots that Codex clients do not commit #893

Description

@0xWinner98

Client or integration

Codex App and Codex CLI

Area

Streaming

Summary

Some OpenAI Responses-compatible gateways return a successful SSE stream but omit canonical fields from lifecycle snapshots. OpenCodex currently relays those snapshots unchanged, and current Codex clients may reject or fail to render the turn even though the upstream request completed with HTTP 200.

The affected payloads are structurally sparse rather than malformed JSON. Examples include lifecycle response objects without output, parallel_tool_calls, tool_choice, or tools; message items without role or content; output_text parts without annotations; reasoning items without summary; and text delta/done events without logprobs.

Expected: an explicit provider-local compatibility option can backfill only missing or structurally invalid canonical fields on the client-facing SSE branch. Existing upstream values must remain authoritative, and the default passthrough path must remain unchanged.

Reproduction

  1. Configure a custom provider with the openai-responses adapter and a Responses-compatible endpoint.
  2. Have the upstream return a successful stream containing sparse lifecycle events equivalent to:
event: response.created
data: {"type":"response.created","response":{"id":"resp_example","object":"response"}}

event: response.output_item.added
data: {"type":"response.output_item.added","item":{"id":"msg_example","type":"message"}}

event: response.output_text.delta
data: {"type":"response.output_text.delta","delta":"hello"}

event: response.completed
data: {"type":"response.completed","response":{"id":"resp_example","object":"response"}}
  1. Send a short request through /v1/responses from Codex.
  2. Observe that the upstream and proxy complete with HTTP 200, while the Codex client may show no final assistant message or fail to commit the response lifecycle.
  3. Compare with the same semantic events after the missing canonical fields are backfilled; the client completes normally.

The sample above is a synthetic, redacted equivalent of the observed wire shape and contains no provider-specific data.

Version

2.10.0 (f9b9440c)

Operating system

macOS 26.5.2 (arm64)

Provider and model

Custom OpenAI Responses-compatible gateway / GPT-compatible routed model

Logs or error output

Upstream HTTP status: 200
Proxy terminal status: completed
Codex client result: no committed final assistant message for the sparse snapshot stream

Screenshots and supporting files

None. A synthetic SSE fixture and regression tests are included in the accompanying PR.

Redacted configuration

{
  "providers": {
    "example": {
      "adapter": "openai-responses",
      "baseUrl": "https://gateway.example/v1",
      "responsesPath": "/responses"
    }
  }
}

Suggested fix

Add a disabled-by-default provider option such as responsesSnapshotRepair. When enabled, apply a client-facing SSE payload rewrite that:

  • backfills only missing or structurally invalid canonical fields;
  • preserves every valid value supplied by the upstream;
  • covers response lifecycle snapshots, output items, content parts, reasoning summary parts, and output-text logprobs;
  • composes with existing image-call and item-ID rewrites;
  • keeps inspection and persistence on the raw upstream bytes;
  • can run inline on the existing explicit Darwin eager-relay path without reintroducing the tee/JS-pull retention shape.

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstreamingSSE, WebSocket, terminal stream frames

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions