Bug: ToolName namespace collision causes 'unsupported custom tool call: execexec' with gpt-5.6-sol (HIGH-PRIORITY)
Effect: The GPT 5.6 models are unusable as they are having issues with tool calling.
Problem
Models using use_responses_lite (e.g. gpt-5.6-sol) emit ResponseItem::CustomToolCall events where the namespace field equals the tool name:
{ "name": "exec", "namespace": "exec", "call_id": "call_abc123", "input": "..." }
The built-in exec handler is registered under ToolName::plain("exec") (namespace: None). When the router constructs a ToolName from the response, it creates ToolName { name: "exec", namespace: Some("exec") }, which doesn't match. The registry lookup fails and the Display impl concatenates namespace + name:
unsupported custom tool call: execexec
This kills the tool execution bridge for the entire session.
Example GPT 5.6 Sol (Ultra) responses:
- I hit a tooling hiccup on my first read command. Retrying with the shell directly so I can keep moving on the repo
inspection.`
- I’m checking the tool surface itself for direct shell access. The collaboration tools are fine; the shell wrapper is
the piece misbehaving, so I’m trying the underlying command entrypoint directly.`
And then it just fails to do anything, ofcourse.
---
Root Cause
ToolName::new(), ToolName::namespaced(), and the derived Deserialize impl preserve the namespace field verbatim from the wire format. There is no normalization to strip a redundant namespace that equals the tool name.
---
Fix (ready to merge)
Affects: codex-rs/protocol/src/tool_name.rs, codex-rs/core/src/tools/router.rs
Normalize ToolName at construction time — when namespace == name, set namespace to None:
| Entry Point | Change |
|---|---|
| ToolName::new() | .filter(\|ns\| ns != &name) |
| ToolName::namespaced() | if namespace == name { None } else { Some(namespace) } |
| Deserialize impl | Replace derived with manual impl delegating to ToolName::new() |
The fix is implemented and tested in my fork:
➡️ Branch: MayukXT/codex:fix/tool-namespace-collision-regression
➡️ Diff: main...MayukXT:fix/tool-namespace-collision-regression
---
Test Results
Unit tests (codex-protocol) — test_tool_name_normalization:
- Covers plain, distinct-namespace, same-namespace construction, and JSON deserialization
- All 241 protocol tests pass ✅
Integration test (codex-core) — build_custom_tool_call_normalizes_equal_namespace_and_name:
- Feeds
CustomToolCall { namespace: Some("exec"), name: "exec" }throughToolRouter::build_tool_call() - Asserts output is
ToolName::plain("exec") - All 328 core tool tests pass ✅
E2E:
- Built CLI from source, ran
codex exec "..."withgpt-5.6-sol - Model emitted
exec/execcustom tool calls — fix normalized them, router dispatched correctly, no error ✅
---
Backward Compatibility
Serializeis untouched — wire format output unchanged- Only
namespace == namecollapses toNone; MCP tools likemcp__python/execare unaffected ToolName::plain()bypasses the filter entirely
---
Fix authored by @MayukXT
8 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
metoo,please OpenAI fit it quickly
GUYS! It's high time with this issue PLEASE FIX! You just need to add this in your code!
尽快修复一下吧,干活时候出现这种问题真的糟心!!
I have same problem. Cannot use chatgpt app right now
I found a possible workaround: when this error occurs, click Continue in new chat (which forks the conversation). In the new chat, tool calls may start working again, allowing the task to continue. This is not guaranteed, but it helped me get past the failure without changing the model or CLI version.
@zhangxaochen yeah! coz the context of the model resets... but doesn't work always, as you said.
I found that sending a simple instruction as user message can temporarily bypass the issue:
This works because GPT‑5.6‑sol will respect that and omit the namespace entirely, so the Codex client receives a plain name field and resolves the tool correctly.