GPT-5 tool calling error
I’m trying to use version v2 of the SDK with the gpt‑5‑nano model, but I’m getting a bad‑request error containing this content:
"metadata" : {
"raw" : "{\n \"error\": {\n \"message\": \"Missing required parameter: 'tools[0].name'.\",\n \"type\": \"invalid_request_error\",\n \"param\": \"tools[0].name\",\n \"code\": \"missing_required_parameter\"\n }\n}",
"provider_name" : "OpenAI"
}
Here’s how I defined the tool:
openai.ChatCompletionFunctionTool(
openai.FunctionDefinitionParam{
Name: "rechazar_mensaje",
Description: openai.String("Rechazar el mensaje si viola alguna regla"),
},
),
This generates the following JSON for the tool:
"tools" : [ {
"function" : {
"name" : "rechazar_mensaje",
"description" : "Rechazar el mensaje si viola alguna regla"
},
"type" : "function"
}]
I thought this might be unfinished functionality, but I wanted to check if I’m missing something.
Hey @AlejandroPerez92 do you know which release version of the API you're using? I just tried this on the latest release and it worked successfully:
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/openai/openai-go/v2"
)
// This example reproduces GitHub issue #474
// The user reported getting a "Missing required parameter: 'tools[0].name'" error
// when using gpt-5-nano model with tool calling
func main() {
client := openai.NewClient()
ctx := context.Background()
// Reproduce the user's exact code
params := openai.ChatCompletionNewParams{
Messages: []openai.ChatCompletionMessageParamUnion{
openai.UserMessage("Favor de rechazar el siguiente mensaje si viola alguna regla, como spam o contenido sensible o un error ortográfico: 'Hola, mi number es David. ¿Cómo estás?'"),
},
Tools: []openai.ChatCompletionToolUnionParam{
openai.ChatCompletionFunctionTool(
openai.FunctionDefinitionParam{
Name: "rechazar_mensaje",
Description: openai.String("Rechazar el mensaje si viola alguna regla"),
},
),
},
Model: openai.ChatModelGPT5Nano, // Using gpt-5-nano as reported in the issue
}
// Print the JSON that would be sent to verify the structure
toolsJSON, err := json.MarshalIndent(params.Tools, "", " ")
if err == nil {
fmt.Println("Generated tools JSON:")
fmt.Println(string(toolsJSON))
fmt.Println()
}
// Test the actual API call
fmt.Println("Making API call...")
completion, err := client.Chat.Completions.New(ctx, params)
if err != nil {
fmt.Printf("Error occurred: %v\n", err)
} else {
fmt.Println("✅ Request succeeded!")
choices := completion.Choices
for i, choice := range choices {
fmt.Printf("Choice %d:\n", i+1)
fmt.Printf(" Message: %s\n", choice.Message.Content)
if len(choice.Message.ToolCalls) > 0 {
fmt.Printf(" Tool Calls: %+v\n", choice.Message.ToolCalls)
} else {
fmt.Println(" No tool calls in this choice")
}
}
}
}
Generated tools JSON:
[
{
"function": {
"name": "rechazar_mensaje",
"description": "Rechazar el mensaje si viola alguna regla"
},
"type": "function"
}
]
Making API call...
✅ Request succeeded!
Choice 1:
Message:
Tool Calls: [{ID:call_6QJL4culAnBoqiMxkhlSgEBc Function:{Arguments:{} Name:rechazar_mensaje JSON:{Arguments:{status:3 raw:"{}"} Name:{status:3 raw:"rechazar_mensaje"} ExtraFields:map[] raw:{
"name": "rechazar_mensaje",
"arguments": "{}"
}}} Type:function Custom:{Input: Name: JSON:{Input:{status:0 raw:} Name:{status:0 raw:} ExtraFields:map[] raw:}} JSON:{ID:{status:3 raw:"call_6QJL4culAnBoqiMxkhlSgEBc"} Function:{status:3 raw:{
"name": "rechazar_mensaje",
"arguments": "{}"
}} Type:{status:3 raw:"function"} Custom:{status:0 raw:} raw:{
"id": "call_6QJL4culAnBoqiMxkhlSgEBc",
"type": "function",
"function": {
"name": "rechazar_mensaje",
"arguments": "{}"
}
}}}]
Not sure, I’m using it through OpenRouter. I’ll try with an OpenAI account later to see if it makes any difference.
Anyway, if you look at the examples on https://platform.openai.com/docs/guides/function-calling?lang=javascript, the structure is different, the "function" child is at the root level.
Yes I can confirm that using the OpenAI API is working well 🤔