Summary
When a client sends an OpenAI Chat Completions or Responses request that includes a tool whose parameters.required array lists fields that do not exist in the parameters.properties map, the proxy forwards the request to Gemini unchanged, and Gemini API rejects it with:
AI_APICallError: GenerateContentRequest.tools[0].function_declarations[N].parameters.required[M]: property is not defined
Reproduction
curl -X POST http://localhost:<port>/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "gemini-2.0-flash",
"messages": [{"role":"user","content":"hi"}],
"tools": [{
"type": "function",
"function": {
"name": "search_company",
"description": "Search",
"parameters": {
"type": "object",
"properties": {"country":{"type":"string"},"industry":{"type":"string"}},
"required": ["country","industry","stale_field","another_stale"]
}
}
}]
}'
Expected behavior
The proxy should strip the stale required entries before forwarding, since util.CleanJSONSchemaForGemini already implements cleanupRequiredFields for exactly this case. The OpenAI spec is lenient about required (some clients add a name and forget to define the property, or generate schemas from Pydantic/Zod models that include intermediate/aliased fields), so the request is valid upstream of the proxy. Gemini, however, is strict.
Root cause
In internal/translator/gemini/openai/chat-completions/gemini_openai_request.go (and the responses counterpart), the code renames tools[].function.parameters to parametersJsonSchema but does not run the renamed payload through util.CleanJSONSchemaForGemini. Other translators (claude->gemini, antigravity->gemini) already do so for the same reason. Without that sanitization step:
cleanupRequiredFields is skipped, so any name in required that is missing from properties is forwarded as-is.
- Other Gemini-incompatible keywords (
const, $ref, patternProperties, x-* extensions, numeric enums, etc.) leak through too.
Proposed fix
Run util.CleanJSONSchemaForGemini on the renamed parametersJsonSchema after the rename, in both translators. This is the same fix shape already used by the claude and antigravity translators.
A draft implementation lives on fix/gemini-tool-required-properties-sanitize in myagizmaktav/CLIProxyAPI. PR incoming.
Summary
When a client sends an OpenAI Chat Completions or Responses request that includes a tool whose
parameters.requiredarray lists fields that do not exist in theparameters.propertiesmap, the proxy forwards the request to Gemini unchanged, and Gemini API rejects it with:Reproduction
Expected behavior
The proxy should strip the stale required entries before forwarding, since
util.CleanJSONSchemaForGeminialready implementscleanupRequiredFieldsfor exactly this case. The OpenAI spec is lenient aboutrequired(some clients add a name and forget to define the property, or generate schemas from Pydantic/Zod models that include intermediate/aliased fields), so the request is valid upstream of the proxy. Gemini, however, is strict.Root cause
In
internal/translator/gemini/openai/chat-completions/gemini_openai_request.go(and the responses counterpart), the code renamestools[].function.parameterstoparametersJsonSchemabut does not run the renamed payload throughutil.CleanJSONSchemaForGemini. Other translators (claude->gemini, antigravity->gemini) already do so for the same reason. Without that sanitization step:cleanupRequiredFieldsis skipped, so any name inrequiredthat is missing frompropertiesis forwarded as-is.const,$ref,patternProperties, x-* extensions, numeric enums, etc.) leak through too.Proposed fix
Run
util.CleanJSONSchemaForGeminion the renamedparametersJsonSchemaafter the rename, in both translators. This is the same fix shape already used by the claude and antigravity translators.A draft implementation lives on
fix/gemini-tool-required-properties-sanitizeinmyagizmaktav/CLIProxyAPI. PR incoming.