Skip to content

OpenAI-compatible non-streaming Responses requests fail on Codex pool (Hindsight 0.10.1) #6162

Closed

Description

@SeanChengN

Client or integration

OpenAI-compatible SDK: Hindsight 0.10.1's openai-responses provider.

Provider or upstream service

OpenAI Codex through an OpenCodex OAuth account pool.

OpenCodex version

Reproduced on 2.64.0. I inspected the v2.69.0 source but have not run this reproduction on 2.69.0, so I am not claiming a runtime failure on that release.

Endpoint or capability

POST /v1/responses, non-streaming requests.

Current behaviour

A non-streaming Responses request reaches the Codex pool but returns HTTP 400 with {"detail":"Stream must be set to true"}. The same model and admission key work with stream:true: HTTP 200 with a response.completed event. OpenCodex's request log identifies the successful route as an OpenAI Codex pool account.

A disposable process using Hindsight 0.10.1's actual OpenAIResponsesLLM.call() path also raises BadRequestError (HTTP 400) with that detail. Hindsight calls responses.create(**params) without setting stream; its normal and tool-call request builders both use this pattern:

Expected behaviour

The official OpenAI Responses create reference defines stream as optional; setting it to true enables server-sent events. An OpenAI-compatible client that omits stream or sets it to false expects a complete JSON Response.

For a Codex upstream that requires SSE, OpenCodex could make the upstream request with stream:true and return a complete JSON Response to a non-streaming client. If this endpoint intentionally supports streaming clients only, please document that limitation so compatible clients can choose another route.

Minimal redacted request or reproduction

curl -i http://127.0.0.1:50000/v1/responses \
  -H 'content-type: application/json' \
  -H 'x-opencodex-api-key: <REDACTED>' \
  -d '{"model":"gpt-6-luna","input":[{"role":"user","content":"Reply PONG"}],"store":false,"stream":false}'

Control: set "stream":true in the same request. It returns HTTP 200 and reaches response.completed.

Actual response or error

HTTP/1.1 400 Bad Request
{"detail":"Stream must be set to true"}

Upstream documentation

OpenAI Responses create reference: stream is optional and enables server-sent events when set to true.

Suggested mapping or implementation notes

A focused implementation should preserve complete output and usage, fail closed when no terminal event arrives, retain the existing storage semantics, and leave stream:true callers unchanged.

Additional context and attachments

The related PR #293 proposed SSE-to-JSON buffering but was closed without merge. Maintainer review identified incomplete reconstruction of tool calls, reasoning summaries, refusals, and annotations; false HTTP 200 on truncated streams; and unintended store changes.

Checks

  • I searched existing provider and compatibility issues.
  • The request and response were redacted.
  • The expected behaviour is based on an upstream specification or a concrete client requirement.

Activity

  1. added
    providerProvider adapters, OpenAI-compat presets, upstream API quirks
    streamingSSE, WebSocket, terminal stream frames
    toolstool_calls, MCP, web-search / sidecar tools
    on Sep 28, 2026
  2. Ingwannu commented on Sep 28, 2026

    @Ingwannu
    Owner

    Confirmed against current dev cbe0d40 (2.70.0) by tracing the request path. The Responses parser preserves omitted/false stream as non-streaming, canonical-forward normalization only defaults an absent store to false, and the passthrough adapter serializes stream unchanged. The Codex backend's stream:true requirement therefore still produces the reported 400.

    #882 is the earlier auto-closed report and #293 was a related implementation attempt closed because reconstruction was incomplete and fail-open. This issue should remain the canonical valid report. Accepting as P2; no more reporter information is needed.

    The fix should separate client negotiation from the mandatory canonical upstream transport: send stream:true upstream, then boundedly reconstruct the complete terminal Response JSON for non-streaming callers. It must preserve explicit store semantics; retain ordered text, annotations, refusals, reasoning summaries, function/custom-tool arguments and usage; leave stream:true callers unchanged; and fail closed on EOF, malformed/oversized frames, read errors, stalls or cancellation without one valid terminal response.

  3. added
    account-poolOAuth, credentials, Codex pool, quota, failover, plans
    bugSomething isn't working
    priority: P2Medium: provider/client-specific bug with a workaround, bounded enhancement tied to a tracked issue,
    on Sep 28, 2026
  4. lidge-jun commented on Sep 29, 2026

    @lidge-jun
    Owner

    Fixed on dev by #6200: a non-streaming caller on the canonical ChatGPT upstream now gets a JSON Responses object folded from an SSE upstream call, so the Stream must be set to true rejection no longer occurs. Client disconnects during the deferred replay no longer publish a completed result, and failed-terminal diagnostics are credential-masked. Ships in the next release; please reopen if Hindsight's non-streaming requests still fail.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    account-poolOAuth, credentials, Codex pool, quota, failover, plansbugSomething isn't workingpriority: P2Medium: provider/client-specific bug with a workaround, bounded enhancement tied to a tracked issue,providerProvider adapters, OpenAI-compat presets, upstream API quirksprovider-compatibilityProvider compatibility reportsstreamingSSE, WebSocket, terminal stream framestoolstool_calls, MCP, web-search / sidecar tools

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions