Skip to content

[BUG] codex Missing required parameter: 'tools[0].name #1914

Description

@tranduykhanh030

OmniRoute Version

3.7.8

Installation Method

npm (global)

Operating System

Linux

OS Version

Debian 12

Node.js Version

22.12.0

Provider(s) Involved

codex

Model(s) Involved

cx/gpt-5.4

Client Tool

codex

Description

OmniRoute upstream fix guide: Codex Responses tools[0].name error

Issue

Codex /v1/responses requests can fail with:

[400]: Missing required parameter: 'tools[0].name'.

Observed route:

/v1/responses | cx/gpt-5.4 | 108 msgs | 7 tools | effort=medium
cx/gpt-5.4 -> codex/gpt-5.4
provider=codex
model=gpt-5.4
sourceFormat=openai-responses
targetFormat=openai-responses
status=400

Concrete failed call metadata from local deployment:

id=a839b502-7e78-4e39-b68d-4cbc85614e0e
timestamp=2026-05-03T12:42:38.589Z
path=/v1/responses
provider=codex
model=gpt-5.4
requestedModel=codex/gpt-5.4
error=[400]: Missing required parameter: 'tools[0].name'.

Sensitive data note

The raw artifact is not included here because it may contain user/project content.
Only redacted structural information is included.

Root cause

The request sent to Codex Responses API contained a mixed tools array.
Some tools were already in Responses API format:

{
"type": "function",
"name": "...",
"description": "...",
"parameters": { ... },
"strict": false
}

But some tools remained in Chat Completions legacy format:

{
"type": "function",
"function": {
"name": "...",
"description": "...",
"parameters": { ... }
}
}

Codex /v1/responses requires function tools to have top-level name.
Therefore a legacy-format tool at tools[0] causes:

Missing required parameter: 'tools[0].name'.

Redacted tool shape from failing payload

Total tools: 7

Tool 0:

  • keys: function, type
  • type: function
  • has top-level name: false
  • has function.name: true
  • has top-level parameters: false
  • has function.parameters: true
  • Result: invalid for Codex Responses API

Tool 1:

  • keys: description, name, parameters, strict, type
  • has top-level name: true
  • Result: valid Responses-style tool

Tool 2:

  • keys: description, name, parameters, strict, type
  • has top-level name: true
  • Result: valid Responses-style tool

Tool 3:

  • keys: description, name, parameters, strict, type
  • has top-level name: true
  • Result: valid Responses-style tool

Tool 4:

  • keys: description, name, parameters, strict, type
  • has top-level name: true
  • Result: valid Responses-style tool

Tool 5:

  • keys: function, type
  • type: function
  • has top-level name: false
  • has function.name: true
  • Result: invalid for Codex Responses API

Tool 6:

  • keys: description, name, parameters, strict, type
  • has top-level name: true
  • Result: valid Responses-style tool

Relevant code

File:

open-sse/executors/codex.ts

Function:

normalizeCodexTools(body)

Current behavior, simplified:

  • If tool.type === "function", it attempts to find a name from either:
    • tool.name
    • tool.function.name
  • If a name exists, the tool is kept.
  • But if the input tool was legacy Chat format, it is not rewritten to Responses format.

The problematic behavior is that this legacy Chat-format tool is accepted:

{
"type": "function",
"function": {
"name": "some_tool",
"description": "...",
"parameters": { "type": "object", "properties": {} }
}
}

But it is still sent upstream in that shape, where Codex Responses requires:

{
"type": "function",
"name": "some_tool",
"description": "...",
"parameters": { "type": "object", "properties": {} }
}

Recommended fix

In normalizeCodexTools(body), normalize all function tools into Codex Responses format before sending upstream.

For function tools:

  1. Accept name from top-level tool.name or legacy tool.function.name.
  2. Accept description from top-level tool.description or legacy tool.function.description.
  3. Accept parameters from top-level tool.parameters or legacy tool.function.parameters.
  4. Rewrite the object to:

{
type: "function",
name,
description,
parameters
}

  1. Remove the legacy function wrapper.

Suggested patch logic

This is the local patch that fixed the issue in production:

const rawName =
  typeof tool.name === "string"
    ? tool.name
    : tool.function &&
        typeof tool.function === "object" &&
        !Array.isArray(tool.function) &&
        typeof (tool.function as Record<string, unknown>).name === "string"
      ? ((tool.function as Record<string, unknown>).name as string)
      : "";
const name = rawName.trim();
if (!name) {
  return false;
}

const functionObject =
  tool.function &&
  typeof tool.function === "object" &&
  !Array.isArray(tool.function)
    ? (tool.function as Record<string, unknown>)
    : null;
const description =
  typeof tool.description === "string"
    ? tool.description
    : typeof functionObject?.description === "string"
      ? functionObject.description
      : "";
const parameters =
  tool.parameters &&
  typeof tool.parameters === "object" &&
  !Array.isArray(tool.parameters)
    ? tool.parameters
    : functionObject?.parameters &&
        typeof functionObject.parameters === "object" &&
        !Array.isArray(functionObject.parameters)
      ? functionObject.parameters
      : { type: "object", properties: {} };

// Codex Responses requires function tools in Responses format:
// { type: "function", name, description, parameters }.
// Some clients/translators can leave Chat Completions tools shaped as
// { type: "function", function: { name, description, parameters } },
// which upstream rejects with Missing required parameter: tools[0].name.
for (const key of Object.keys(tool)) {
  delete tool[key];
}
tool.type = "function";
tool.name = name;
if (description) tool.description = description;
tool.parameters = parameters;

validToolNames.add(name);
return true;

Important behavior

This fix should preserve already-valid Responses-format tools.

Input:

{
"type": "function",
"name": "a",
"description": "desc",
"parameters": { "type": "object", "properties": {} }
}

Output should stay:

{
"type": "function",
"name": "a",
"description": "desc",
"parameters": { "type": "object", "properties": {} }
}

Legacy input:

{
"type": "function",
"function": {
"name": "a",
"description": "desc",
"parameters": { "type": "object", "properties": {} }
}
}

Output should become:

{
"type": "function",
"name": "a",
"description": "desc",
"parameters": { "type": "object", "properties": {} }
}

Suggested tests

Add unit tests for normalizeCodexTools or the Codex request preparation path.

Test 1: preserves Responses-format tool

Input:

{
"tools": [
{
"type": "function",
"name": "search",
"description": "Search docs",
"parameters": {
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"]
}
}
]
}

Expected:

{
"tools": [
{
"type": "function",
"name": "search",
"description": "Search docs",
"parameters": {
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"]
}
}
]
}

Test 2: converts Chat Completions legacy tool to Responses format

Input:

{
"tools": [
{
"type": "function",
"function": {
"name": "search",
"description": "Search docs",
"parameters": {
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"]
}
}
}
]
}

Expected:

{
"tools": [
{
"type": "function",
"name": "search",
"description": "Search docs",
"parameters": {
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"]
}
}
]
}

Test 3: filters invalid function tools without any name

Input:

{
"tools": [
{
"type": "function",
"function": {
"parameters": { "type": "object", "properties": {} }
}
}
]
}

Expected:

{
"tools": []
}

Test 4: mixed tools array

Input should include:

  • one Responses-format function tool
  • one Chat-format function tool
  • one invalid function tool without name

Expected:

  • first tool preserved
  • second tool converted
  • invalid tool removed

Deployment verification from local fix

After applying the local patch, rebuilding, restoring env, and restarting, verification showed:

tools[0].name count since new process: 0
Missing required parameter count since new process: 0
gpt-5.4 400 count since new process: 0
gpt-5.4 200 count since new process: 15

Service health after patch:

MainPID=193524
NRestarts=0
ExecMainStatus=0
Description=OmniRoute 3.7.8 + kiro-opus45-fix
ActiveState=active
SubState=running
cwd=/opt/omniroute/releases/3.7.8
HTTP=307
DB=ok
env_match=yes
build_id=UNg0gR4BPH45cDSd1n0sW

Conclusion

This is a tool normalization bug in the Codex Responses path.
The fix is to convert legacy Chat Completions function tools into Responses API function tools before sending to Codex /v1/responses.

Filtering/validating name is not enough. The object shape must be rewritten so every function tool has top-level name and parameters.

Steps to Reproduce

Missing required parameter: 'tools[0].name

Expected Behavior

Missing required parameter: 'tools[0].name

Actual Behavior

Missing required parameter: 'tools[0].name

Test Impact

Needs a new unit test

Error Logs / Output

Screenshots

No response

Additional Context

No response

Validation Plan

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions