Skip to content

[Provider compatibility] DeepSeek V4 Flash returns 400 when developer message is interleaved between function_call and function_call_output #1292

Description

@c3right

Client or integration

Codex App (Windows desktop)

Area

Tools / Responses continuation / provider compatibility

Summary

deepseek/deepseek-v4-flash on the native openai-responses route returns HTTP 400 when Codex sends a continuation whose input history contains a developer message between a function_call and its matching function_call_output.

The tool itself executes successfully, the function_call_output is present, and the call_id matches exactly. The failure is structural/interleaving-related:

function_call(call_id=X)
→ message(role=developer, content=...)
→ function_call_output(call_id=X, output=successful tool result)

Upstream error:

No tool output found for tool call X.

This is reproducible and reversible in one workspace. The developer message content is sourced verbatim from a local task_plan.md context file. Temporarily renaming that file makes the same DeepSeek tool call succeed; restoring it makes the 400 return immediately.

Important nuance: the exact Codex-side mechanism that injects this developer message is not yet identified. We initially suspected a planning-with-files PostToolUse hook, but static inspection ruled that out as the direct source: that hook only emits a short fixed reminder and does not read task_plan.md. The failing request nevertheless contains a developer message matching the beginning of task_plan.md verbatim.

Reproduction

Environment A (failing workspace):

  1. Open a Codex workspace that contains a non-empty task_plan.md and where the current Codex context-injection setup causes part of that file to appear as a developer message in Responses history.
  2. Select deepseek/deepseek-v4-flash with Max effort.
  3. Start a fresh conversation.
  4. Trigger exactly one shell tool call, for example:
Get-Content -Path "D:\AI\storycard\README.md" -TotalCount 5
  1. The first DeepSeek Responses request returns HTTP 200 and emits the tool call.
  2. Codex executes the command successfully.
  3. The follow-up /v1/responses request is sent, but the relevant input order is:
function_call(call_id=X)
message(role=developer, text copied from task_plan.md)
function_call_output(call_id=X, output="Exit code: 0 ...")
  1. DeepSeek returns HTTP 400:
No tool output found for tool call X.

A/B/ABA validation on the same workspace:

  • task_plan.md present: failure reproduced deterministically (5/5 observed failures in prior sessions).
  • Rename only task_plan.mdtask_plan.md.disabled, leaving progress.md, findings.md, AGENTS.md, hooks, model, workspace and OpenCodex unchanged: the same single-tool DeepSeek test succeeds.
  • Restore the exact original task_plan.md (SHA256 verified identical): a fresh DeepSeek session immediately reproduces the same 400 again.
  • On the restored failure, logs again show function_call → developer message from task_plan.md → function_call_output, with identical call IDs and a real successful tool result.

Control workspace:

  • Same machine, same DeepSeek model, same OpenCodex, but an empty workspace with no task_plan.md: 28/28 observed tool-result continuation requests returned HTTP 200, with 0 cases where a developer message appeared between a function_call and its function_call_output.

Model control:

  • In the failing workspace, GLM/glm-5.2 executes the same tool successfully even when developer messages are interleaved between function calls and outputs. So this appears specific to the DeepSeek Responses compatibility path, not the shell command or workspace permissions.

Version

Known reproduction: OpenCodex 2.10.2.

The issue still reproduced immediately after upgrading OpenCodex on 2026-08-08. The latest published release at report time is v2.11.0; the exact post-upgrade local ocx --version output was not captured before filing, so please treat 2.10.2 as the exact confirmed version and v2.11.0 as the likely/current upgraded build pending confirmation.

Codex App on the reproducing machine:

  • About version: 26.730.61639 (released 2026-08-05)
  • Windows package: OpenAI.Codex 26.730.8199.0

Operating system

Windows 11 LTSC

PowerShell 7.6.3

Provider and model

Official DeepSeek provider

  • Routed model: deepseek/deepseek-v4-flash
  • Adapter: openai-responses
  • Inbound protocol: responses
  • Requested effort: max

Logs or error output

Representative failing follow-up request:

{
  "model": "deepseek-v4-flash",
  "provider": "deepseek",
  "inboundProtocol": "responses",
  "requestedModel": "deepseek/deepseek-v4-flash",
  "requestedEffort": "max",
  "status": 400,
  "errorCode": "invalid_request_error",
  "upstreamError": "No tool output found for tool call call_00_...",
  "attempts": [
    {
      "adapter": "openai-responses",
      "status": 400,
      "sendCount": 1,
      "recoveryKinds": []
    }
  ]
}

The immediately preceding request in the same conversation returned HTTP 200 with non-zero output/reasoning tokens. The tool command then executed successfully. The next request reached OpenCodex and upstream, but returned the 400 above.

Detailed local log inspection confirms:

function_call(call_id=call_00_sp4OLJNqwFpIzzZ8jpDl6521)
→ message(role=developer, text verbatim from task_plan.md)
→ function_call_output(call_id=call_00_sp4OLJNqwFpIzzZ8jpDl6521, output=successful command result)

The call IDs are identical; the output is not missing.

Screenshots and supporting files

Available if useful. We have:

  • Codex UI screenshots of the tool execution followed by the 400;
  • OpenCodex raw log entries for the preceding HTTP 200 and failing HTTP 400;
  • logs_2.sqlite evidence for the 5/5 failing workspace vs 28/28 successful control workspace;
  • ABA reversible test evidence (task_plan.md present → fail, renamed → pass, restored → fail).

Redacted configuration

The failing machine uses the built-in DeepSeek provider routed through openai-responses. No project-local provider override is involved. The control and failing workspaces share the same global OpenCodex/provider/tool configuration.

No secrets are included in this report.

The workspace has a planning-with-files setup, but inspection showed its PostToolUse hook is not the direct source of the full task_plan.md developer message. The exact Codex-side injection mechanism remains unknown.

Expected behavior

OpenCodex's DeepSeek Responses compatibility path should correctly handle Codex histories where a developer/system message is interleaved between a function_call and the matching function_call_output, or normalize the history into a provider-compatible ordering before forwarding upstream.

At minimum, a valid matching function_call_output with the same call_id and successful tool result should not be treated as missing solely because another message appears between the pair.

Actual behavior

The follow-up request reaches DeepSeek but returns HTTP 400:

No tool output found for tool call <call_id>

This makes DeepSeek unusable as a tool-using executor in affected Codex workspaces while GLM and other paths continue to work.

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, credentials, and private data.
  • I reproduced the issue in fresh DeepSeek conversations.
  • I verified the tool command itself succeeds.
  • I verified function_call and function_call_output use the same call_id.
  • I performed a reversible single-variable A/B/ABA test.
  • I compared against a clean workspace and another routed model.

References

Related but distinct from #875 (DeepSeek V4 Flash Responses route stalls after tool calls). In this report the follow-up request is sent and reaches upstream, but returns a concrete 400. This matches the "follow-up is sent and 400s" branch discussed during #875 triage rather than the older "no follow-up request is sent" failure mode.

If maintainers want, I can provide a sanitized local capture of the exact continuation input around the function_call / developer message / function_call_output triplet.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingtoolstool_calls, MCP, web-search / sidecar tools

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions