openai / openai/codex

responses: function_call_output can be emitted without call_id and fails strict upstreams (400)

Open
#42,088 13 comments 8 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app app-server bug custom-model tool-calls
Dominant language
Rust
Stars
125k
Forks
19.5k
PR merge metrics
PR metrics pending

Description

Environment
  • Codex Desktop 26.825.51511 / app-server 0.151.0-alpha.7.2
  • Upstream: a strict OpenAI-compatible /responses server (e.g. DeepSeek)
Symptom

Resuming an existing thread, or sending a message into a thread that contains a prior tool call, fails with:

Failed to deserialize the JSON body into the target type: input: missing field `call_id` at line 1 column ~...
Root cause

A response_item of type: "function_call_output" in the replayed input array carries id, name, namespace, output, and internal_chat_message_metadata_passthrough, but is missing call_id. The Responses API requires call_id on function_call_output to link it to the matching function_call. Strict deserializers (e.g. DeepSeek) reject the entire request at the wire layer, so a single dangling item breaks every message in the thread.

Minimal repro shape:

{
  "type": "function_call_output",
  "id": "...",
  "name": "...",
  "namespace": "",
  "output": [{"type": "output_text", "text": "..."}],
  "internal_chat_message_metadata_passthrough": {}
  // missing: "call_id"
}
Related
  • #42067 — earlier report of this class of failure
  • #41690 — automation + DeepSeek + missing call_id
  • #41799
  • Tool parameters schema oneOf/null causing similar strict-serde failures: #37786, #30523
Expected behavior

Pick one (preferably the first):

  1. Always emit call_id on function_call_output, sourced from its matching function_call.
  2. Omit function_call_output items that have no corresponding function_call in the same request (dangling outputs are invalid).
  3. At minimum, validate/normalize input before serialization so a malformed item cannot fail-close the whole request.
Suggested fix location

The thread/session serialization path that reconstructs input items on restore/continue. A function_call_output should either carry a call_id that matches its function_call, or be dropped when unmatched.

Impact

Any strict /responses upstream cannot resume/replay threads containing such an item; one missing call_id fails the whole stream.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the thread/session serialization path that reconstructs input items during restore or continue, focusing on function_call_output handling. Trace how each output is matched to a function_call, then verify the behavior with a strict Responses upstream: every emitted output should have a matching call_id, or unmatched items should be omitted before serialization.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.