GPT-5.5 tool calls fail with "unsupported call: exec_commandexec_command" — model sends self-referential namespace on built-in tool calls
Title
GPT-5.5 tool calls fail with unsupported call: exec_commandexec_command — model sends self-referential namespace on built-in tool calls
Environment
- macOS, Apple Silicon
- Codex CLI: 0.143.0 (Homebrew cask,
/opt/homebrew/bin/codex) - Model affected:
gpt-5.5 - Known-working model:
gpt-5.4 - Reproduces in both Codex Desktop and
codex exec
Problem
Every tool call GPT-5.5 makes is rejected by the local tool router:
codex_core::tools::router: error=unsupported call: exec_commandexec_command
GPT-5.5 retries indefinitely; every attempt fails identically. gpt-5.4 works with the identical binary, repo, and sandbox settings.
Minimal reproduction
codex exec -m gpt-5.5 --sandbox read-only "You must use the shell tool to run: pwd"
→ error=unsupported call: exec_commandexec_command, retried until exhausted.
codex exec -m gpt-5.4 --sandbox read-only "You must use the shell tool to run: pwd"
→ succeeds normally.
Root cause (confirmed via rollout logs + source trace)
I diffed the raw function_call items actually recorded in the local session rollout JSONL for a failing GPT-5.5 run against a working GPT-5.4 run (~/.codex/sessions/<date>/rollout-*.jsonl):
GPT-5.5 (failing):
"type":"function_call","name":"exec_command","namespace":"exec_command","arguments":"{...}"
GPT-5.4 (working):
"type":"function_call","name":"exec_command","arguments":"{...}"
(no namespace field at all)
GPT-5.5's Responses API output is attaching a self-referential namespace: "exec_command" to calls on the built-in exec_command tool. GPT-5.4 never sets this field for built-in tools.
Tracing what the client does with that field (at rust-v0.143.0):
codex-rs/core/src/tools/router.rs(build_tool_call) takes the model'sResponseItem::FunctionCall { name, namespace, .. }and doesToolName::new(namespace, name)directly — no validation against what's actually registered.codex-rs/core/src/tools/registry.rs(dispatch_any_with_terminal_outcome→self.tool(&tool_name)) looks up the handler by an exact{name, namespace}match. The built-in shell tool is registered asToolName::plain("exec_command")(namespace: None), so the incoming{name:"exec_command", namespace:Some("exec_command")}matches nothing and falls into the "unsupported call" branch.codex-rs/protocol/src/tool_name.rs,impl fmt::Display for ToolName:
``rust`
match &self.namespace {
Some(namespace) => write!(f, "{namespace}{}", self.name),
None => f.write_str(&self.name),
}
namespace
There's no separator between and name, which is why the error text is the tool name glued to itself: exec_commandexec_command`.
I also confirmed via diff (rust-v0.142.0...rust-v0.143.0) that registry.rs, router.rs, and tool_name.rs are unchanged between those two releases, and the namespace field already existed on ResponseItem::FunctionCall in 0.142.0. So this isn't a client-side regression in 0.143.0 — the trigger is server-side GPT-5.5 behavior, and the client has apparently never validated/sanitized an unrecognized namespace on a built-in tool call.
Two distinct bugs here
- (Likely server-side / model-behavior) GPT-5.5's Responses API attaches a spurious self-referential
namespaceto built-in (non-MCP) tool calls, which no other model does. - (Client-side, codex-rs)
build_tool_call/ the tool registry have no fallback when a call'snamespacedoesn't match any registered namespace for that tool name — worth at least falling back to a name-only match for built-in tools, or logging a clear diagnostic instead of a silently-mangled error string. Separately,ToolName'sDisplayimpl should insert a separator (e.g.{namespace}.{name}or{namespace}/{name}) so error messages involving a namespaced tool are legible instead of concatenated.
Workaround
Force gpt-5.4:
codex -m gpt-5.4
or in ~/.codex/config.toml:
model = "gpt-5.4"
Related but not identical
- #19486 — GPT-5.5 server-side tool-schema failure
- #24431 — broader GPT-5.5 reliability degradation
- codex-plugin-cc#270 — GPT-5.5 failure where GPT-5.4 succeeds
18 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Thanks for the duplicate flags — confirming and adding what I've found since filing, in case it's useful for triage.
Cross-referencing: #31609 is the same bug with the same error text. #31656 is valuable extra evidence — it shows this isn't
exec_command-specific: on Codex App Remote SSH the same self-namespacing hitslist_mcp_resourcesandlist_mcp_resource_templatestoo (unsupported call: list_mcp_resourceslist_mcp_resources, etc.), which matches the client-side mechanism below (any built-in tool call is vulnerable, not just the shell tool). #31617 and #31611 independently report that downgrading Codex CLI fixes it, which I want to correct/refine below since I initially assumed a downgrade wouldn't help.Root cause (client-side mechanism, confirmed via source + my own rollout logs):
Comparing a failing GPT-5.5 session against a working GPT-5.4 session in my local
~/.codex/sessions/**/rollout-*.jsonl, the rawfunction_callitems differ like this:"type":"function_call","name":"exec_command","namespace":"exec_command",..."type":"function_call","name":"exec_command",...(nonamespacefield)GPT-5.5 is attaching a self-referential
namespace(equal to the toolname) to built-in tool calls; GPT-5.4 never does. Tracing what Codex does with that:codex-rs/core/src/tools/router.rs(build_tool_call) buildsToolName::new(namespace, name)straight from the model'sResponseItem::FunctionCall, with no validation against what's actually registered.codex-rs/core/src/tools/registry.rs(self.tool(&tool_name)) does an exact{name, namespace}match. Built-in tools are registered asToolName::plain(name)(namespace: None), so the incoming{name:"exec_command", namespace:Some("exec_command")}matches nothing → falls into the "unsupported call" branch.codex-rs/protocol/src/tool_name.rs'sDisplayimpl forToolNamedoeswrite!(f, "{namespace}{}", self.name)— no separator — which is why the error text is the tool name glued to itself.Correction on the regression window: I originally diffed
rust-v0.142.0...rust-v0.143.0and foundregistry.rs/tool_name.rs/router.rsunchanged, and concluded downgrading wouldn't help. That was wrong — I was diffing against the wrong baseline. #31617 downgraded tocodex-cli 0.142.5and #31611 downgraded to@openai/codex@0.140.0, both npm/version numbers that predaterust-v0.143.0. Diffingrust-v0.142.5...rust-v0.143.0instead,codex-rs/core/src/tools/router.rsdid change in that window (aTurnContext→StepContextrefactor, plusCustomToolCallgaining namespace handling it didn't have before), alongside the "MCP tools now use tool search by default" feature landing in 0.143.0. I can't fully pin from client-side diffs alone whether it's that router refactor, the tool-search-default flip changing what's presented to the Responses API, or a GPT-5.5-side rollout coinciding with the same date — but empirically:I downgraded my own Homebrew install (macOS arm64) straight to the
rust-v0.142.5release binary (swapped/opt/homebrew/bin/codexto point at therust-v0.142.5codex-aarch64-apple-darwinasset, bypassing the cask) and re-ran the exact repro:This now succeeds — GPT-5.5 runs the shell tool correctly, no
unsupported callerror. So the downgrade reports in #31617/#31611 check out and are the best current workaround, better than pinning-m gpt-5.4if you want GPT-5.5's quality with tool use.Suggested fix directions, independent of pinning down the exact server-side trigger:
{name, namespace}lookup misses and the name matches a registered built-in tool — turns a guaranteed failure into a successful dispatch, and is safe since it only ever fires on a call that would otherwise hard-fail anyway.ToolName'sDisplayshould insert a separator betweennamespaceandnameregardless, so future instances of this class of error are legible instead of concatenated.tool_search-default-on rollout in 0.143.0 (#29486) is what's nudging GPT-5.5 into emitting namespaced calls for tools that were never registered under a namespace.Happy to help verify a fix against 0.143.0 + gpt-5.5 once one's up — my original detailed writeup with more session-log samples is above.
Same: Title: Agent shell calls fail with "unsupported call: exec_commandexec_command"
Product: Codex
Severity: Blocker — agent cannot execute any shell command
Observed behavior:
Every agent-initiated shell call, including
pwd, fails before execution with:unsupported call: exec_commandexec_command
Expected behavior:
The shell tool should execute
pwdand return the working directory.Important distinction:
Running
pwdthrough <user_shell_command> succeeds:Exit code: 0
Output: /home/examiner/projects/get-lost-in-portland
Troubleshooting completed:
This suggests tool registration or backend dispatch is combining the
namespace/function name incorrectly.
Environment:
I can independently reproduce this issue on Ubuntu under WSL.
Environment
0.143.00.140.0@openai/codex)gpt-5.5mediumv22.22.110.9.4/home/user/projectFailure on 0.143.0
In a fresh Codex session, I asked Codex to run only basic read-only commands:
The first captured rejected tool call was:
exec_command/home/user/projectThe raw rejection was:
The rejected call was also reported as:
Subsequent attempts with trivial commands such as:
were all rejected before the shell command actually ran.
Fresh-session confirmation
I then opened a completely new Codex session on
0.143.0and repeated a minimal execution-tool smoke test.The new session also failed to execute the basic commands.
So this was not limited to one corrupted conversation/thread.
A/B downgrade test
I downgraded only the Codex CLI package:
Then I opened another fresh Codex session in the same environment and repeated:
All commands executed successfully.
Observed successful behavior included:
and:
Local A/B result
This looks like a regression affecting tool-call routing or tool-name construction rather than a shell, Git, repository, or command-specific failure.
I have not attached auth files, local state databases, conversation history, or private repository contents. I can provide additional sanitized diagnostics if useful.
Also observed on my setup. Without tools, Codex would be just ChatGPT in terminal. This is a serious bug that should be fixed immediately.
downgrade to 0.140.0 worked for me.
I'm encountering the same issue in a local Codex CLI session.
The command does not appear to reach the shell at all. Even simple commands such as
pwdandlsfail before execution.Codex shows the tool call as:
With arguments similar to:
But the returned error is:
I also reproduced the same failure with commands such as:
All of them fail with the same
unsupported call: exec_commandexec_commanderror before the command is actually executed.This looks like a tool routing or tool-name serialization issue, where
exec_command.exec_commandis being collapsed or duplicated intoexec_commandexec_command. It does not appear to be related to the shell command itself, project path, permissions, or proxy configuration, since no command reaches the terminal.Environment:
I can confirm the same issue on my machine.
Environment:
Minimal repro:
Confirmed on macOS 26.5 arm64 with Codex CLI 0.143.0 installed globally
through npm/NVM (Node 24.18.0, npm 11.18.0).
Two fresh sessions failed before process creation. One rendered:
unsupported call: exec_commandexec_command
and the next rendered:
unsupported call: exec_command
Both
pwdand a read-onlysedcommand failed with no exit code. Restartingwhile remaining on 0.143.0 did not help. Downgrading only the CLI to 0.142.5
immediately restored built-in command execution.
Originally reported as #31740; closing that report as a duplicate.
Confirming and adding two data points not yet in this thread:
1. Still broken on the latest alpha. Reproduced identically on
0.144.0-alpha.4(not just0.143.0), so whatever's in that alpha didn't touch this path.2. Not scoped to
unified_exec. Ran with--disable unified_execon gpt-5.5 — the malformed call just renames itself:unsupported call: shell_commandshell_commandinstead ofexec_commandexec_command. Same self-referential-namespace shape, different built-in tool. So this isn't something users can dodge via feature flags; the router has no fallback for any built-in tool oncenamespace == name.3. Confirms the false-negative risk worth flagging loudly: I tested with a canary file (
cata file containing a random string only the shell could read). Under gpt-5.5 it failed 3x and correctly reported it couldn't verify the contents. But a plainpwdrequest under the same broken model returned the correct answer without ever executing anything — it inferred cwd from context already visible in the session banner. So affected users may not notice command execution is fully broken unless they test with something the model can't guess. Given @rymalia and @yuanchangsai77's reports above that downgrading the CLI (not just the model) to0.142.5/0.140.0restores execution while staying on gpt-5.5 — that seems like the most promising lead for a workaround that doesn't require giving up gpt-5.5, worth digging into what capability the newer CLI is advertising that the older one isn't (possibly the model only emits the malformednamespacewhen the client signals support for namespaced/nested tool calls).Env: Codex CLI 0.143.0 and 0.144.0-alpha.4, npm global install, Ubuntu 24.04 x86_64,
sandbox_mode = "danger-full-access".Reproduced this on macOS (Darwin, arm64) with Codex CLI 0.143.0 installed via npm (@openai/codex). Same symptom: gpt-5.5 tool call gets rejected as
unsupported call: exec_commandexec_command,list_mcp_resourceslist_mcp_resourcesAlso:
With
model_provider = "openai"(the default), gpt-5.5 hits the namespace-duplication bug above. Calls fail, retry, and often eventually get through after several rounds, burning a lot of tokens along the way.With
model_provider = "openai_https"(a custom provider block,wire_api = "responses", no lite flag set), gpt-5.5 gets rejected outright by the API itself instead:``
``{"error":{"message":"This model is not supported when using X-OpenAI-Internal-Codex-Responses-Lite.","type":"invalid_request_error","param":"model","code":"unsupported_value"}}
gpt-5.4 was clean.
For those still hitting tool-calling issues (namespace doubling, broken HTML rendering): before rolling back to 0.142.5, check whether your install is actually complete.
My symptoms matched what's being reported here, but the root cause turned out to be a missing platform binary —
@openai/codex-linux-x64— not a version regression. The globalnpm install -ghad silently skipped the optional dependency, leaving an incomplete install regardless of version.Fix (Linux x64):
That installs
codex-linux-x64into the correct nested location. Currently running 0.143.0 without issue — tool calls passing, HTML rendering correctly.Independent confirmation via Codex internal logs (
logs_2.sqlite)Adding router-side trace evidence from a separate repro on macOS arm64, standalone install (not Homebrew/npm), in case it helps triangulate the client-side fix.
Environment
0.143.0standalone (~/.codex/packages/standalone/releases/0.143.0-aarch64-apple-darwin)gpt-5.5,model_reasoning_effort = "medium",approvals_reviewer = "auto_review"exec_command, zero onapply_patchWhat the local trace shows
From
~/.codex/logs_2.sqlite, the failure path incodex_core::tools::router:dispatch_duration_ms=0,handler_duration_ms=12— the router rejects the name in-dispatcher, before any process spawn. Matches the reporter'sToolName::Displayconcatenation finding:Some(namespace) + namewith no separator →exec_commandexec_command.Cross-check
apply_patchtool calls in the same failing turns route correctly (noapply_patchapply_patchin logs) → consistent with the reporter's finding that only the namespaced built-in (exec_command) trips the lookup, sinceapply_patchwas not emitted with anamespacefield by GPT-5.5 in these turns.stringsthatdispatch_tool_call_with_code_mode_resultexists in both 0.142.5 and 0.143.0 binaries — supporting the reporter's diff result that the regression is not inrouter.rs/registry.rs/tool_name.rsbetween those tags. The trigger is the server-sidenamespacefield on GPT-5.5 built-in tool calls; 0.142.5 only appears "fixed" because users on it generally were not yet driving GPT-5.5 against that codepath.Workaround that worked here
Rolling the
currentsymlink back to0.142.5and pinning~/.codex/version.json(dismissed_version: "0.143.0") restored working state, but as noted above this only sticks because the auto-update check is suppressed — the underlying client-side namespace-handling gap remains for any future GPT-5.x that emitsnamespaceon built-in tools. Switching togpt-5.4per the reporter's workaround also resolves it without a downgrade.Happy to provide the raw
logs_2.sqlitequery output or the exact SQL if useful for the fix.Can also confirm this on macos
Confirming on Linux x86_64 (Ubuntu 26.04,
@openai/codex0.143.0 via npm, node 22, ChatGPT auth over the websocket responses API), and adding a data point I haven't seen in this thread: the trigger correlates with the login shell advertised to the model ($SHELL).With
SHELLpointing at zsh, every built-in call arrives self-namespaced and fails as described (RUST_LOG=codex_api=traceshowsname: "exec_command", namespace: Some("exec_command"); the first call's arguments also carry"shell":"zsh"). WithSHELL=/bin/bashand the exact same prompt, the calls arrive with nonamespacefield and execute normally on unmodified 0.143.0:Notes:
ZDOTDIRpointing at an empty directory.--enable unified_exec_zsh_fork,--enable shell_zsh_fork,--enable non_prefixed_mcp_tool_namesall still fail;--disable unified_execjust moves the failure toshell_commandshell_command.$SHELLalone toggles whether GPT-5.5 emits the self-referential namespace.exec_commandattempts, the model sometimes fabricates the command output in its final answer as if the command had run. Inexecmode with no visible error, this silently produces made-up results.So besides downgrading,
SHELL=/bin/bash(e.g. in a small wrapper aroundcodex) is a workaround that keeps 0.143.0 + gpt-5.5 usable, at the cost of the model driving bash instead of zsh.Reproducable and also present with the latest release on Arch Linux; occuring even with complete purge of files when installing vithe AUR, npm, and the curl'd bash script.
I ran the public issue description through Rootlyze as a quick test.
Likely pattern: model-version tool-call schema drift — GPT-5.5 emits a self-referential namespace on built-in tool calls, and the local router treats it as part of the tool name.
Evidence from the issue: GPT-5.5 sends
name="exec_command"plusnamespace="exec_command", while GPT-5.4 sends the same tool call withoutnamespace. The router then resolves it asexec_commandexec_command, rejects it, and the model retries the same failing call.Next check: verify whether built-in tools should ignore
namespacewhen it equals the tool name, or fall back to a name-only lookup when namespace lookup fails.Prevention: add a compatibility guard that strips self-referential namespaces for built-in tools and logs unknown namespace fields instead of producing a doubled tool name.
Limitation: based only on the public issue text, not the full trace/log.
If you have a sanitized trace, I can run the full version through Rootlyze. Please remove secrets, API keys, tokens, customer data, credentials, and private URLs first.
The 0.142.5 → 0.143.0 trigger, pinned from source: gpt-5.5's model-catalog entry newly sets
include_skills_usage_instructions: true, and the instructions it injects teach dotted-namespace tool addressingBuilding on @growthringsadvisory's trace (which pinned the dispatch mechanism and the regression window but left the trigger open between the router refactor, the tool-search flip, and a server-side rollout) — I diffed the window file-by-file and believe the trigger can be pinned to one model-catalog field.
**1. The dispatch path is byte-identical across the window — so the regression is in what the client sends, not how it dispatches.**
core/src/tools/registry.rsandprotocol/src/tool_name.rs: identical betweenrust-v0.142.5andrust-v0.143.0(diff -qclean).core/src/tools/router.rs: theResponseItem::FunctionCallarm is identical in both versions (ToolName::new(namespace, name), no validation). The only namespace-related router change in the window isCustomToolCallnewly preserving namespaces (#30302) — a different item type than the failingfunction_calls.2. The only bundled model-catalog change for gpt-5.5 in this window is a single field. Diffing
models-manager/models.jsonbetween the tags, thegpt-5.5entry changes in exactly one way:include_skills_usage_instructions: (absent) → true. Cross-checks:gpt-5.4has it false/absent (works); on currentmain, all threegpt-5.6-*models have itfalse— and none of the 5.6 reports show this particular failure — whilegpt-5.5still has ittrue.3. The field is brand-new in 0.143.0 — a 0.142.5 client cannot even parse it.
include_skills_usage_instructionsappears nowhere in therust-v0.142.5tree (not inmodels.json, not inprotocol/src/openai_models.rs). So even if model info is refreshed from a remote catalog, downgraded clients are structurally immune. That makes every "downgrade fixes it" report (here, #31617, #31611, #31639) consistent with a client-shipped trigger, with no need to assume a coincident server-side model change.4. What the flag injects is instruction text that demonstrates dotted-namespace tool calls. When the flag is true,
core/src/context/available_skills_instructions.rsappendsSKILLS_HOW_TO_USE_WITH_ABSOLUTE_PATHS/..._WITH_ALIASESto a developer-role context fragment. That text repeatedly addresses tools innamespace.nameform: "must be accessed throughskills.listandskills.read", "callskills.listwith{"authority":{"kind":"orchestrator"}}", "pass itsmain_resourcetoskills.read". This is a new source of dotted tool addressing in the default context for gpt-5.5 sessions, introduced in exactly the failing window, gated to exactly the failing model.Putting it together: gpt-5.5 sessions on ≥0.143.0 receive instructions demonstrating
namespace.nameaddressing; the model generalizes the convention to plain built-in tools and emits a self-referentialnamespace— visible as"namespace":"exec_command"in the rollout logs above, and literally rendered dotted asexec_command.exec_commandin @pzy19-prog's report. The unchanged exact-match registry lookup then rejects the call, and the separator-lessDisplayprints the gluedexec_commandexec_command. #31656'slist_mcp_resourceslist_mcp_resourcesis the same mechanism hitting another plain tool.Falsifiable predictions, checkable by anyone affected:
skills.list/skills.readtext); gpt-5.4 sessions on the same client should not.gpt-5.6-sol/terra/lunaon the same client (flag is false for those) — consistent with reports so far.Fix directions this supports (each independently sufficient):
include_skills_usage_instructions: falseforgpt-5.5, or rewordSKILLS_HOW_TO_USE_*so it stops demonstrating dotted addressing to models that over-generalize it. (The 5.6 models shipping withfalsesuggests the per-model targeting is deliberate and cheap to revise.)ToolRegistrylookup when the exact{name, namespace}lookup misses (only fires on calls that would otherwise hard-fail), plus a separator inToolName'sDisplayso future instances of this class stay legible. As of currentmain, the lookup is still exact-match-only andDisplaystill concatenates without a separator.Caveat: this is static analysis over the tagged sources plus the logs already in this thread — I haven't run a live gpt-5.5 session. Happy to be corrected by anyone who can flip the flag locally and observe the behavior change.