Skip to content

fix(ai): keep optional object tool parameters typed for Gemini - #355

Merged
shuv1337 merged 1 commit into
integration-v2from
gemini-tool-schema
Aug 14, 2026
Merged

fix(ai): keep optional object tool parameters typed for Gemini#355
shuv1337 merged 1 commit into
integration-v2from
gemini-tool-schema

Conversation

@shuv1337

Copy link
Copy Markdown
Collaborator

Problem

Every Gemini tool call failed with HTTP 400 INVALID_ARGUMENT when any registered tool declared an optional object parameter:

GenerateContentRequest.tools[0].function_declarations[53].parameters
  .properties[cursor_theme].properties: only allowed for OBJECT type

Cause

projectNode in gemini-tool-schema.ts dropped a node's own type whenever the input used a JSON Schema nullable union, and re-expressed it as a combiner instead:

["type", types ? (types.length === 0 ? "null" : undefined) : schema.type],
["anyOf",  : types && types.length > 0 ? types.map((type) => ({ type })) : undefined],

So type: ["object", "null"] projected to anyOf: [{ type: "object" }] with no type at all. Gemini reads properties and required only on an OBJECT-typed node, so it rejected the entire request — one such parameter anywhere in the tool set broke every call in the session.

The file already flattened the equivalent anyOf: [{…}, { type: "null" }] input correctly to type: "string", nullable: true. The array form simply never got the same treatment, so two spellings of the same schema projected differently.

MCP servers emit the array form routinely for optional object parameters, which is how this surfaced.

Fix

Project a single non-null type back onto type, and keep the combiner only for a genuine multi-type union. This makes both input spellings agree.

Verification

  • New tool-schema-projection case covering the MCP shape — red before the fix, green after.
  • End to end against the live Antigravity provider with the offending MCP server enabled: 5/5 successful responses, previously 0/5. Also confirmed on gemini-3.7-flash-medium, gemini-3.7-flash-low, gemini-3.6-flash-high, and gemini-3.1-pro-high.
  • Captured wire body now carries "type": "object", "nullable": true with no remaining type unions.
  • bun typecheck clean; oxlint reports 0 warnings and 0 errors on the changed files.

One existing assertion changed

gemini.test.ts asserted type: ["string","null"]{ nullable: true, anyOf: [{ type: "string" }] }. That encoded the bug: the same test already expected the equivalent anyOf input to produce { type: "string", nullable: true }. Multi-type unions are untouched and still assert anyOf.

Pre-existing failures

packages/ai has 7 failures on integration-v2 today (Azure api-key header, OpenRouter reasoning details, Bedrock Mantle bearer auth). I reproduced the identical 7 at the parent commit in a separate workspace: 515 tests / 7 fail before, 516 tests / 7 fail after. No regressions from this change.

A JSON Schema nullable union such as `"type": ["object", "null"]` projected to
`anyOf: [{ type: "object" }]` and dropped the node's own `type`. Gemini reads
`properties` and `required" only on an OBJECT-typed node, so it rejected the whole
request with INVALID_ARGUMENT and every tool call to the model failed. MCP servers
emit that shape for optional object parameters.

Project a single non-null type back onto `type` and keep the combiner only for a
real multi-type union, matching what the equivalent `anyOf` input already produced.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shuvbot found no summary-only findings.

@shuv1337
shuv1337 merged commit 98174c7 into integration-v2 Aug 14, 2026
4 of 5 checks passed
@shuv1337
shuv1337 deleted the gemini-tool-schema branch August 14, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant