Repository navigation
[Bug]: Responses passthrough UUID item IDs leave Codex turn stuck on Thinking #938
Description
Client or integration
Codex App
Area
Streaming
Summary
When an openai-responses passthrough provider emits UUID item IDs instead of canonical Responses prefixes, the upstream request completes and OpenCodex records HTTP 200 plus reported usage, but Codex App never produces an assistant item or completes the turn. The UI remains on Thinking until the user interrupts it.
This is distinct from #864. The stream contains a complete response.completed event, and switching macOS from the default relay path to streamMode: "eager-relay" does not change the result.
The incompatible IDs observed on the wire look like:
response.id = b16df59f-bbc4-458f-80c6-eae4bac8dada
reasoning.id = 4ffa2f22-7283-43ae-ae18-7690736424c1
message.id = 6d66799f-6b2b-4643-8d30-5176244a3a8b
Canonical OpenAI Responses item IDs use type prefixes such as resp_, rs_, and msg_. OpenCodex already has an opt-in responsesItemIdRepair, but it only repairs exact, preconfigured placeholder IDs or missing terminal IDs. It cannot repair randomly generated UUIDs that change on every request.
Reproduction
- Configure an API-key provider using
adapter: "openai-responses"whose native Responses endpoint returns UUID IDs for response/message/reasoning objects. - Set
statelessResponses: trueand route a model through it. - Start a new Codex App turn with a minimal input such as
Reply only OK. - Observe that the provider returns the complete sequence:
response.created
response.output_item.added # reasoning item with UUID id
response.reasoning_text.delta
response.output_item.done
response.output_item.added # message item with UUID id
response.output_text.delta
response.output_text.done
response.output_item.done
response.completed # status=completed, output and usage present
- OpenCodex logs the request as
status: 200,usageStatus: "reported", and includes token usage fromresponse.completed. - Codex App remains on Thinking. Its rollout contains
task_startedand the user input, but no assistant response item and no successful turn completion. Interrupting the UI producesturn_aborted.
I also repeated the request after setting:
{"streamMode":"eager-relay"}The Codex CLI JSON stream still emitted only thread.started and turn.started; it emitted neither an agent message nor turn.completed. This rules out the macOS tee() relay path as the cause.
Directly calling the same OpenCodex /v1/responses route with curl shows that the SSE stream and response.completed frame are complete; the differentiating protocol violation is the UUID item IDs.
Version
2.10.0
Operating system
macOS 26.5.2 (Darwin 25.5.0, Apple Silicon arm64)
Provider and model
OpenAI-compatible native Responses provider / deepseek-v4-flash and deepseek-v4-pro
Logs or error output
# OpenCodex persisted request summary
status=200
usageStatus=reported
inputTokens=14466
outputTokens=81
reasoningOutputTokens=49
# Codex rollout lifecycle
task_started
# no assistant response_item
# no turn_completed
turn_aborted reason=interruptedSuggested fix
Extend ResponsesItemIdRepairConfig with a provider-local option such as:
{
"responsesItemIdRepair": {
"repairInvalidIds": true,
"repairMissingTerminalIds": true
}
}In responses-item-id-repair.ts, when repairInvalidIds is enabled, rewrite any existing message or reasoning ID that does not start with its expected prefix:
const shouldRepair = state.placeholders[type].has(rawId)
|| (state.repairInvalidIds && !rawId.startsWith(REPAIRABLE_PREFIXES[type]));
const mapped = shouldRepair
? mintCanonicalId(type, state.scope, outputIndex)
: state.repairMissingTerminalIds
? rawId
: null;The request-local mapping should be applied consistently to:
response.output_item.added.item.id- lifecycle event
item_idfields response.output_item.done.item.idresponse.completed.response.output[].id
Function-call IDs and call_id should remain untouched. Because the rewrite is client-facing only, raw upstream snapshots can remain available for provider replay.
Redacted configuration
{
"providers": {
"provider": {
"adapter": "openai-responses",
"baseUrl": "https://redacted.example",
"responsesPath": "/responses",
"authMode": "key",
"models": ["deepseek-v4-flash", "deepseek-v4-pro"],
"statelessResponses": true
}
},
"websockets": false
}Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Activity
github-actions commentedon Aug 3, 2026
Automated translation bookkeeping — detected language: unknown.
address review feedback for deepseek responses repair
Ingwannu commentedon Aug 3, 2026
Confirmed against current
dev: this is a valid Responses compatibility defect and is distinct from #864. The upstream stream reachesresponse.completed, but non-canonical UUID response/message/reasoning IDs are left intact and Codex does not commit the lifecycle.PR #940 implements the relevant provider-local opt-in SSE normalization. I have reviewed it and requested corrections for a cross-type alias collision and an unbudgeted alias-map growth path; its current head is not merge-ready. Keeping this issue open until the corrected PR passes the full CI and the reporter confirms the repaired stream completes.
address review feedback for deepseek responses repair
fix type-scoped aliases and enable built-in deepseek repair
fix(deepseek): canonical item-id repair for UUID message/reasoning ids (
fix(deepseek): backfill the registry item-id repair policy on the liv…
fix(deepseek): canonical item-id repair for UUID message/reasoning ids (
fix(deepseek): backfill the registry item-id repair policy on the liv…
Merge pull request #1027 from lidge-jun/codex/stack-05-uuid-item-ids
fix(deepseek): normalize item ids on both bounded-JSON paths
lidge-jun commentedon Aug 5, 2026
Fixed on
devin #1027 (merged as2d7aa907c).DeepSeek's Responses route emits bare UUID item IDs where Codex expects the canonical
msg_/rs_prefixes, which is what left the client stuck on Thinking. Message and reasoning IDs are now normalized on the client-facing path; raw recorded snapshots are untouched, and function-call IDs are left exactly as they arrive.The bounded-JSON paths from #875 normalize identically, so the two fixes agree instead of one disabling the other.
Thanks to @mouzhi (#940) — the ID-prefix diagnosis is that PR's. The rest of that branch (response-ID aliasing, reasoning-event conversion, envelope synthesis) was left out as outside this issue's boundary and is still on the table separately if the stall persists.
Not in a release yet. This is on
dev, andmainis atv2.10.0. It ships in the next release.fix(deepseek): restore live upstream streaming on the Responses wire
fix(deepseek): repair content_part item_id on streamed reasoning items (
fix(deepseek): normalize item ids on both bounded-JSON paths
fix(deepseek): canonical item-id repair for UUID message/reasoning ids (
fix(deepseek): backfill the registry item-id repair policy on the liv…
Merge pull request lidge-jun#1027 from lidge-jun/codex/stack-05-uuid-…
fix(deepseek): restore live upstream streaming on the Responses wire
fix(deepseek): repair content_part item_id on streamed reasoning items (