Skip to content

Injected function_call_output without call_id bricks the whole thread (Windows + DeepSeek Responses, app-server 0.154.0-alpha.6.2) #45227

Open

Description

@linlongfei688-lab

Summary

On Windows with a custom provider using wire_api = "responses" (DeepSeek), inputs injected by the app server as a standalone function_call_output are sent without a call_id. The provider rejects the request with HTTP 400 and the bad item is persisted into the rollout, so the whole thread — including plain user messages — fails from then on.

Related: #41690 (Windows/DeepSeek), #43515 (macOS/Kimi), #41799 (Azure).

Error (verbatim)

Failed to deserialize the JSON body into the target type: input: missing field call_id at line 1 column 88555 (type: invalid_request_error)

Environment

  • Windows 10 Pro 19045 (zh-CN)
  • Codex Desktop app build 26.908.40834; embedded app-server / command-runner 0.154.0-alpha.6.2 (windows-x86_64)
  • Provider [model_providers.deepseek]: base_url https://api.deepseek.com/ , wire_api = "responses", API-key auth
  • Model deepseek-v4-flash, reasoning effort high

Steps to reproduce

  1. Sign in with a custom Responses-compatible provider and an API key.
  2. Open a thread and attach a heartbeat / cron automation (or use create_thread / send_message_to_thread delegation).
  3. When it fires, the injected standalone function_call_output has id/name/namespace/output but no call_id; the first request fails in ~1 s with HTTP 400, the item is persisted, and every later turn of that thread fails identically.

Observed failures (16 distinct turns)

2026-09-09 18:46:18Z col 274443; 20:46:20Z col 276054; 22:31:53Z col 71761; 22:46:52Z col 277225; 2026-09-10 00:47-04:49Z x6 cols 278396 / 279567 / 286213 / 287897 / 288090 / 292214; 10:28:07Z col 292359; 2026-09-13 12:31:21Z col 88555; 12:40:13Z col 89716; 12:42:58Z col 91591; 12:44:06Z col 67518. Timestamps match a 2-hour heartbeat cadence.

Impact

3 threads affected (one with a 70 MB rollout); no recovery path in the UI; the only working fix is manually editing the rollout JSONL to convert/remove the orphaned item.

Note on a wrong local diagnosis

This is not an "~88 KB request-body limit": the reported column is just the offset of the malformed item, and the same error appeared at 16 different offsets (67,518 -> 292,359).

Suggested fix

Never emit standalone function_call_output items without call_id (or convert injected inputs into message items); validate the outgoing payload and drop/repair orphaned items; surface a recoverable error instead of permanently failing the thread.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    windows-osIssues related to Codex on Windows systems
    app-serverIssues involving app server protocol or interfaces
    custom-modelIssues related to custom model providers (including local models)
    on Sep 13, 2026
  2. Cekxri commented on Sep 13, 2026

    @Cekxri

    Additional data point from Windows + Agent Router (OpenAI-compatible Responses API), same app-server 0.154.0-alpha.6.2.

    • Provider: Agent Router, wire_api = "responses", model deepseek-v4-flash.
    • Reproduction: calling send_message_to_thread from thread A into thread B injects a standalone function_call_output with id / name / namespace / output but no call_id, and with no matching function_call. The first request fails with HTTP 400 input: missing field call_id. The malformed item is persisted into thread B's rollout, so subsequent plain user messages in thread B also fail.
    • Minimal wire-level probes against the same provider:
      1. Orphan function_call_output with a random call_id but no matching function_call -> HTTP 400: No tool call found for tool output with call_id ....
      2. Synthetic paired function_call + matching function_call_output (same generated call_id, name send_message_to_thread, namespace codex_app) -> HTTP 200 with response.created / response.in_progress / response.output.
    • This shows the provider accepts the correct pair; the app is emitting only the orphan output. Suggested fix: when injecting a standalone function_call_output, also emit a matching function_call with the same call_id (or normalise the injection to a message if that is the intended semantics), validate the outgoing payload, and avoid persisting the malformed item.

    No API keys, private conversation content, or local paths are included.

  3. dajiaohuang commented on Sep 13, 2026

    @dajiaohuang

    The cross-provider reproductions show a standalone function_call_output without a call_id, followed by a provider rejection and a persisted malformed item. Before patching, could maintainers confirm the intended app-server representation for an injected cross-thread message: a paired function_call and output, a normal message item, or another typed envelope? This affects protocol compatibility and malformed-item recovery.

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

    appIssues related to the Codex desktop appapp-serverIssues involving app server protocol or interfacesautomationsbugSomething isn't workingcustom-modelIssues related to custom model providers (including local models)windows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions