Skip to content

[Bug]: Routed exec_command call carrying {"input": ...} is not repaired, so the client rejects every call with missing field cmd #5370

Closed

Description

@konstantinosbotonakis

Client or integration

Codex App

Area

Tools / MCP / web search

Summary

A routed model can emit a call named exec_command whose arguments are {"input": "<shell command>"}. By the time it reaches the client the call is still named exec_command, so the alias in normalizeDeclaredToolName did not apply, which is the documented behaviour when the catalog declares a bare bridge name. Nothing repairs the argument key either, so the client rejects it with:

failed to parse function arguments: missing field \`cmd\` at line 1 column 127

and the command never runs.

What I expected: since the request declares exec_command with cmd required, a body that carries a single string input should be repaired to {"cmd": ...}, the same way sibling shapes already are:

  • unwrapFreeformToolInput unwraps {"input": ...} for the freeform exec and apply_patch bodies, with fallback keys including cmd and command.
  • compileCodeModeHelperInput remaps command to cmd for the shell_command helper.
  • normalizeDeclaredToolName maps nested helper names back to exec when the catalog declares code mode.

Reproduction

  1. Route a Codex App session to opencode-go/deepseek-v4.1-flash through the proxy, with openai_base_url pointed at the local proxy.
  2. Ask for work that needs shell commands.
  3. The model emits exec_command with {"input": "cd <dir> && sed -n '1,120p' file.ts"}.
  4. The client answers with the error above and the call does not run.

Observed in one session, from the local rollout file:

  • 138 calls named exec_command with {"input": ...}, all 138 rejected with the message above.
  • The same model ran 215 code-mode exec calls correctly in the same session, so routing and the tool pipeline work.
  • The failures start exactly when the thread switches from another routed model to this one, and one of them carries code-mode JavaScript (const { exec_command } = tools; ...) inside that input. It reads like the model kept the nested helper's name and borrowed the parent exec tool's input key.
  • It never adapted: 138 identical rejections, no change of shape.

Version

2.59.0

Operating system

macOS (darwin arm64)

Provider and model

opencode-go/deepseek-v4.1-flash

Logs or error output

failed to parse function arguments: missing field \`cmd\` at line 1 column 127
failed to parse function arguments: missing field \`cmd\` at line 1 column 3677

Screenshots and supporting files

None.

Redacted configuration

{
  "openai_base_url": "http://127.0.0.1:10100/backend-api/codex"
}

The affected turn's catalog declared the code-mode exec tool next to a bare shell bridge name.

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

  1. github-actions commented on Sep 20, 2026

    @github-actions
    Contributor

    Issue reopened

    The report now contains the information required by the automated check. Thanks for updating it.

  2. Ingwannu commented on Sep 21, 2026

    @Ingwannu
    Owner

    Confirmed as a real narrow compatibility gap on current dev at 2fb2dfb947a9aa669e6a1a7c7974109f407f509e.

    The flat catalog case deliberately keeps a genuinely declared bare exec_command as exec_command; that name decision is correct. The missing step is schema-bound argument repair. The existing completed-function-call repair has the original declared schema available, but currently repairs only unsafe integer representations. Thus {"input":"..."} reaches a function that requires cmd unchanged and Codex rejects it.

    I will prepare a focused repair only when all of these are true: the completed call resolves to the exact unnamespaced declared exec_command, its schema requires a string cmd, cmd is absent, and the payload is exactly one string input member. It must not rewrite namespaced/MCP tools, objects with additional fields, non-string input, an existing cmd, malformed JSON, streaming partials, or schemas that do not establish that unambiguous contract. Buffered and SSE completion coverage should pin the same result.

  3. Ingwannu commented on Sep 21, 2026

    @Ingwannu
    Owner

    Fix candidate opened as #5395. The repair is deliberately schema-bound and completion-only; it does not rename the real flat tool or rewrite arbitrary/namespaced input fields. Focused JSON/SSE/replay, structure, and typecheck coverage is green. @lidge-jun please review after exact-head hosted CI completes.

  4. konstantinosbotonakis commented on Sep 22, 2026

    @konstantinosbotonakis
    ContributorAuthor

    Closing this as you guys merged it: #5395

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

    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