BadRequestError (function_response.name empty) when replying to tool_calls with empty id via OpenAI Compatibility Layer

2. Issue Summary for Google Gemini API Forum/Tracker:

Subject: BadRequestError (function_response.name empty) when replying to tool_calls with empty id via OpenAI Compatibility Layer

Environment:

  • API Endpoint: Google Generative Language API (via OpenAI Compatibility Layer - https://generativelanguage.googleapis.com/v1beta/openai/)
  • Model: gemini-2.5-pro-exp-03-25 (or specify your model)
  • Library: openai Python library (specify version, e.g., v1.16.1)
  • Language: Python 3.10

Problem Description:

When using the OpenAI Python library to interact with Gemini models via the compatibility endpoint, if the model returns a tool_calls response where the id field is an empty string (id: ''), the subsequent attempt to send the corresponding tool result back to the API fails.

Steps to Reproduce:

  1. Send a chat completion request with tools defined (client.chat.completions.create).
  2. Receive a response from the Gemini model containing a tool_calls block where tool_calls[0].id == ''.
  3. Execute the requested tool locally.
  4. Construct the message history for the next API call, including:
    • The original messages.
    • The assistant message containing the tool_calls block (with the empty id).
    • A new message with role: 'tool', providing a tool_call_id (e.g., a placeholder like 'unknown_id_...' or even the empty string ''), the correct name of the function, and the stringified content result.
  5. Send this updated message history back to the chat completions endpoint.

Observed Behavior:

The second API call fails with a openai.BadRequestError (HTTP 400). The error message reported by the API is:
* GenerateContentRequest.contents[3].parts[0].function_response.name: Name cannot be empty.
(Note: The index [3] might vary but points towards the role: tool message)

Expected Behavior:

The API should accept the role: tool message, ideally matching it via the name or gracefully handling the empty id from its own previous response, allowing the conversation to proceed.

Evidence/Debugging:

  • Logs confirm the tool_calls block received from the first API call contains id: ''.
  • Deep debugging logs (injecting logging into the openai library’s _base_client.py) confirm that the messages list being sent in the second (failing) API call does contain the role: 'tool' message with the correct, non-empty name field populated.
  • Despite the name field being present in the payload constructed by the library, the Google endpoint still rejects it, claiming the name is empty.

Workaround:

The current workaround is to detect tool_calls with empty IDs in the application layer and skip sending the corresponding role: tool message back to the API. This prevents the BadRequestError but breaks the tool-use flow for that turn.

Request:

Could the Gemini team investigate why the OpenAI compatibility endpoint rejects validly formed role: tool messages (containing the required name) when they correspond to an initial tool_calls request that had an empty id? Is the empty id the expected behavior, and if so, how should clients correctly reply with tool results in this scenario using the OpenAI message format?

1 Like

I’m seeing something different, seems like the OpenAI client sets content to null when using a tool and Google responds with a 400.

[{
  "error": {
    "code": 400,
    "message": "Expected string or list of content parts, got: null",
    "status": "INVALID_ARGUMENT"
  }
}
]

1 Like

Facing the same issue with gemini-2.0-flash-lite. Suggested workaround would degrade the results.