Skip to content

fix(gemini): sanitize schema keywords in function responses to prevent 400 - #3411

Open
AhooraZen wants to merge 1 commit into
decolua:masterfrom
AhooraZen:fix-gemini-tool-response-schema-refs
Open

AhooraZen wants to merge 1 commit into
decolua:masterfrom
AhooraZen:fix-gemini-tool-response-schema-refs

Conversation

@AhooraZen

Copy link
Copy Markdown
Contributor

Problem

When tool output (e.g. from webfetch or JSON schema files) contains keys like $ref, $defs, #, or /, tryParseJSON parses them into the functionResponse.response object.

Google Gemini / Antigravity protobuf parser treats these keys as schema references rather than payload data, failing with:

{"error":{"code":400,"message":"The referenced name `#/$defs/Config` in function_response.response does not match to a display_name in the function_response.parts.","status":"INVALID_ARGUMENT"}}

Solution

  • Added sanitizeFunctionResponseResult in open-sse/translator/formats/gemini.js to recursively sanitize forbidden schema characters ($, #, /, definitions) in tool result objects before constructing functionResponse.
  • Added unit test in scripts/test-gemini-tool-response-sanitization.mjs.

afandiaziz added a commit to afandiaziz/9router that referenced this pull request Aug 20, 2026
afandiaziz added a commit to afandiaziz/9router that referenced this pull request Aug 20, 2026
…/security/providers

Verified via trial-merge + per-PR tests (84 pass/0 fail), OAuth baseline
identical, providers baseline additive-only (+reasonix/ovh/joycode/openmodel).

PRs: decolua#3411 decolua#3370 decolua#3369 decolua#3368 decolua#3393 decolua#3366 decolua#3395 decolua#3382 decolua#3359 decolua#3408 decolua#3357
     decolua#3379 decolua#3380 decolua#3381 decolua#3396 decolua#3338

Co-Authored-By: Claude <noreply@anthropic.com>
@xingxiulaomo

Copy link
Copy Markdown

Thanks for this fix — I can confirm this reproduces in the wild on the current release, which supports your diagnosis.

Environment

  • 9Router v0.5.75 (latest on npm, self-hosted), antigravity provider
  • Client: opencode (opencode.ai), model ag/gemini-3.8-flash

Trigger
A tool call returned a JSON Schema as its tool output. That output contained the opencode config schema, specifically:

"anyOf": [
  { "$ref": "#/$defs/PermissionActionConfig" },
  { "additionalProperties": { "$ref": "#/$defs/PermissionRuleConfig" } }
]

The very next upstream request failed with:

[antigravity/gemini-3.8-flash] [400]: {
  "error": {
    "code": 400,
    "message": "The referenced name `#/$defs/PermissionActionConfig` in function_response.response does not match to a display_name in the function_response.parts.",
    "status": "INVALID_ARGUMENT"
  }
}

The referenced name in the error is exactly the value of the $ref key present in the tool output, which matches the schema-reference behavior you describe. Note your Test 1 payload ("$ref": "#/$defs/Config") is exactly this shape.

Other observations

  • master (v0.5.75) still does not contain sanitizeFunctionResponseResult, so users on the latest npm release are still hitting this. No published version ships the fix yet.
  • On the client side this surfaces as a stall/backoff ("reset after ~28s") after a single schema-carrying tool output, so it's annoying in practice, not just a one-off error.

Thanks again — would be great to see this merged.

@AhooraZen

AhooraZen commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor Author

@qh775885 I switched from OpenCode to Claude Code, So I Completely forgot about this😅 - wondering why it's not merged into master - hopefully it will

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.

3 participants