Skip to content

[Bug]: Cursor Opus 5.5 code-mode exec rejected on 2.84.0 while structured tool controls pass #7049

Closed

Description

@GAOHANG-G

Client or integration

Codex App

Area

Provider adapter

Version

@bitkyc08/opencodex 2.84.0. Both the running /healthz proxy and desktop executable report 2.84.0. Codex task runtime: 0.162.0-alpha.17.2.

Operating system

Windows, 25H2, OS build 26200.9445, x64.

Provider and model

cursor / claude-opus-5-5, requested route cursor/claude-opus-5-5, reasoning effort low, ordinary non-Fast model.

Logs or error output

exec call had invalid freeform arguments; expected {input:string}
errorCode=invalid_request_error
failureStage=semantic-output
failureCause=payload-rejected
sideEffectEvents=0

Redacted configuration

{
  "provider": "cursor",
  "requestedModel": "cursor/claude-opus-5-5",
  "requestedEffort": "low",
  "catalogToolMode": "code_mode_only",
  "catalogShellType": "unified_exec",
  "nativeLocalExec": "unset/default"
}

Summary

On OpenCodex 2.84.0 / Windows / Codex App, a fresh cursor/claude-opus-5-5 task fails to create a small offline SVG HTML because the Cursor adapter rejects code-mode exec calls before host execution:

exec call had invalid freeform arguments; expected {input:string}

Small structured function-tool round trips with the same model/account succeed through both Responses and Messages. These controls do not demonstrate that Codex's real freeform/code-mode surface works.

Environment

  • Running OCX proxy and desktop version: 2.84.0.
  • Codex task runtime: 0.162.0-alpha.17.2.
  • Requested model: cursor/claude-opus-5-5; logged provider: cursor; resolved model: claude-opus-5-5; requested effort: low.
  • Routed catalog row: tool_mode: code_mode_only, shell_type: unified_exec.
  • cursor.nativeLocalExec and provider codexToolMode: unset (default).
  • The model is present in live model discovery. Network connectivity is sufficient for the positive controls.
  • Local-patch disclosure: this installation has existing Qoder CN and Claude Desktop/model-metadata compatibility patches. The relevant Cursor files (protobuf-events.ts, tool-schemas.ts, native-exec.ts, tool-guidance.ts, tool-wording.ts, tool-naming.ts, tool-definitions.ts) were checked against the verified 2.84.0 npm tarball and are byte-identical. The entire installation is not claimed to be pristine.

Reproduction

  1. Start a fresh Codex App task, choose ordinary cursor/claude-opus-5-5, low effort (not Fast).
  2. Ask it to create a new isolated folder and a small self-contained index.html: an original pelican riding a bicycle SVG animation, no network/old assets/dependencies.
  3. Limit the work to one write and one read-back/static validation. Explicitly instruct it to use only request-advertised tools, and use nested tools.apply_patch / tools.exec_command inside exec when code mode is exposed.
  4. Observe repeated OCX 400 records with the exact freeform-wrapper error above, no executable tool call reaching the host, and no HTML file.
  5. The task ultimately stops and reports that it could not use the execution surface.

Sanitized evidence

The fresh test lasted 218.6 seconds and completed without a deliverable.

Request OCX logged status Duration Result
A 400 57.8 s invalid freeform exec arguments
B 400 45.9 s same error
C 400 38.2 s same error
D 200 73.3 s final explanation, no file
  • A–C: errorCode=invalid_request_error, failureStage=semantic-output, failureCause=payload-rejected, sideEffectEvents=0; usage unreported.
  • D: the usage record reports 51,754 total tokens. This is not the aggregate usage for all four requests or a final billing claim.
  • Host rollout: zero executable function/custom-tool calls and zero execution results. A coordination/delegation input envelope is present, but it is not host execution.
  • Actual filesystem check: target index.html does not exist.
  • Model narration says a native Write operation was rejected and that it could not find exec. This narration is not taken as proof that exec was absent: the adapter logs positively show exec payload validation failures. The exact offending upstream argument payload was not captured, so its shape is unknown.

Positive controls (same model, isolated protocol harness)

Advertise one function tool named exec_command with a {cmd:string} schema. Request a single harmless PowerShell stdout marker, execute the validated call on the client, send its real exit status/stdout back, and require the exact marker as the final answer.

  • POST /v1/responses: PASS, ~14.8 s, one real host call, exit 0, correct stdout, successful continuation.
  • POST /v1/messages: PASS, ~54.4 s, same real host execution/result/final-answer checks.

The harness executes only the exact allowlisted command. It is a structured-tool control, not a freeform exec test or a Claude Desktop UI test. It separates connectivity/model routing from the failing Codex code-mode contract.

Local audit / expected behavior

The installed Cursor schema advertises CURSOR_FREEFORM_INPUT_SCHEMA with required input:string. In protobuf-events.ts, commitToolCall checks cursorFreeformWrapperValid(finalArgs); a failure becomes dropInvalidFreeformCall and terminates the request before host execution.

Please investigate the actual upstream argument shape and declaration/normalization path for Cursor Claude code-mode calls. Possible safe repairs should be based on captured payloads and keep fail-closed validation, byte-consistent streaming, and host-owned execution/permissions. Please do not solve this by globally enabling Cursor-native local execution. No such setting was enabled in this test.

We found no verified safe configuration-only workaround. Prompt-level bridge instructions did not prevent the failure. No local Cursor adapter code change or further expensive retry was attempted.

Related reports / distinction

Checks

  • I searched existing issues and documentation.
  • Kept observed failure, model narration, and root-cause hypotheses separate.
  • I removed secrets, tokens, account details, request credentials, and personal data.
  • Stopped the bounded reproduction; no continuing retry or background task remains.

中文简述:Opus 5.5 的小型结构化工具调用可正常执行和回传,但真实 Codex code-mode 写 HTML 任务仍连续报 exec freeform 参数不合约,最终零本机工具执行、无产物。需排查 Cursor Claude 的参数封装/工具声明适配,不能仅凭 HTTP 200 或模型自述判断成功。

Activity

  1. added
    catalogModel catalog, slugs, visibility, routed entries
    toolstool_calls, MCP, web-search / sidecar tools
    on Oct 13, 2026
  2. github-actions commented on Oct 13, 2026

    @github-actions
    Contributor

    Issue reopened

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

  3. changed the title [-][Bug] Cursor Opus 5.5 code-mode exec rejected on 2.84.0 while structured tool controls pass[/-] [+][Bug]: Cursor Opus 5.5 code-mode exec rejected on 2.84.0 while structured tool controls pass[/+] on Oct 13, 2026
  4. added
    bugSomething isn't working
    providerProvider adapters, OpenAI-compat presets, upstream API quirks
    on Oct 13, 2026
  5. lidge-jun commented on Oct 13, 2026

    @lidge-jun
    Owner

    Root cause found; the fix is in #7069.

    What rejects the call. The Cursor adapter checks every completed freeform call before emitting it (commitToolCall → cursorFreeformWrapperValid in src/adapters/cursor/protobuf-events.ts). That check accepted only a string input field. The shared Responses repair that runs after the adapter is more lenient. unwrapFreeformToolInput (src/responses/apply-patch-envelope.ts) also accepts one alternate string field when input is absent: code, script, js, javascript, command, cmd, or content for exec, and patch or content for apply_patch. Claude models commonly name a JavaScript body code. The Cursor gate therefore threw a fatal invalid_request_error on a payload the downstream bridge already knows how to unwrap. That matches the report: failureStage=semantic-output, zero side effects, and a model that "could not find exec."

    A second, smaller defect on the same path. decodeCursorArgsMap JSON-parses every string arg value. For a freeform body that happens to be valid JSON text ({}, 42, null), input became a non-string and hit the same rejection.

    What the fix does

    • The gate applies the same rule the bridge uses: no input key and exactly one recognized string field. It then re-emits {input}. A canonical wrapper stays byte-identical. Two candidate fields, non-string values, unparseable text, and namespaced tools still fail closed.
    • Freeform string args decode without the JSON re-parse.
    • The rejection message now ends with the key shapes it saw, for example (received keys [program:string]), and never the values. The offending payload was not captured here; if Opus sends another shape, the next log will show it.
    • Native local execution is unchanged and stays opt-in.

    Limits. I could not reproduce live, because this machine has no Cursor account, so code is the most likely shape but not a captured one. If the error still appears after #7069 ships, the new suffix in the OCX log will show the actual keys. Please paste that line here.

  6. lidge-jun commented on Oct 13, 2026

    @lidge-jun
    Owner

    Fixed by #7069 — Cursor freeform gate now accepts the shared single-fallback unwrap (e.g. code → input) and preserves JSON-looking freeform string bodies.

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 workingcatalogModel catalog, slugs, visibility, routed entriesproviderProvider adapters, OpenAI-compat presets, upstream API quirkstoolstool_calls, MCP, web-search / sidecar tools

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions