Repository navigation
Gemini: every request fails with HTTP 400 when a tool schema contains $ref / $defs / additionalProperties #10904
Replies: 5 comments
|
The declaration path this report measures now has a plugin, and your cases C and D are what it removes.
Mount it before the row that connects your MCP servers: - insert:
- id: mcp-schema-normalizer
name: '@argszero/dsh-mcp-schema-normalizer'
config: { mode: observe } # observe first: reports what normalize would change, changes nothingThree things I would rather state than let you discover: It is not on the registry yet. 0.2.0 is committed on the repository's Your second half stands, and I verified it here instead of taking it on trust. The A plugin rewrites what the model is told, not what the provider accepts. A The field-level |
|
@argszero — installed 0.2.1 ( It does work on the MCP sideMeasured from the session log's
The 207 Two things still reject the requestI fed the real post-normalisation schemas straight to
So, two findings: 1. Your prediction about the built-in half held exactly. 2. A gap in the rule set. Even after Limitation of my runI could not finish the obvious follow-up — strip everything and see whether it finally returns I agree with the seam you drew: MCP declarations belong to the plugin, built-in declarations belong to core, and #10167's |
|
This comes up a lot with MCP tools, because many servers generate their schemas from Pydantic or Zod, and those emit |
|
Both of your remaining findings come from the same three places, so here is the chain rather than another rule. Line numbers are at 1. Nothing between a tool and the adapter filters a schema.
2. The twelve survivors are structural, not a rule you and I missed. 3. A request-time listener cannot finish this either. What follows for the fix. It belongs where the request is serialized for one route — a Gemini normalization step in On What I have not measured, so will not claim: I have not run the normalizer against a live On the threshold you could not finish: it should not need a bisect. Each rejection names the offending field, so one request per tool — each tool sent alone — tells you which tools are survivable, and the union of the failing ones is the set that has to go. |
|
Thanks, this chain is more useful than another rule. It shows the schema is an opaque object from |
Uh oh!
There was an error while loading. Please reload this page.
Summary
When a session has any tool loaded whose
parametersJSON Schema uses$ref,$defs, oradditionalProperties, every request to a Google Gemini model fails with:Because the full tool catalog is re-sent on each turn, the session becomes completely unusable on that provider — the failure is unrelated to the user's message content. Switching the same conversation to an OpenAI-compatible provider (
deepseek-account/deepseek-flash) works normally, which shows the tool schemas are valid JSON Schema; the incompatibility is specific to the Gemini request path in DSH.DSH appears to forward MCP/built-in tool schemas to Gemini verbatim. Gemini's
functionDeclarations[].parametersonly accepts an OpenAPI 3.0 subset and rejects unknown keys outright.Environment
0.2.1-rc.3(nightly, desktop profile, Windows x64)https://generativelanguage.googleapis.com/v1beta/models/<model>:generateContentgemini-3.8-flash, also reproduced ongemini-3.7-flashapi: openai-completions-style provider entry under@deepseek-ai/dsh-llm-pi-ai,google:with default baseURL@deepseek-ai/dsh-mcp-client(REA MCP server) +zhipu_search_apiMinimal reproduction
Send a
generateContentrequest directly to the Gemini endpoint, changing only the tool schema. All four requests use the same model, key, andcontents.One-liner curl for the failing case:
Remove the
toolsarray (or flatten the schema) and the same request returns200.Observed matrix
200 OKobject/properties/string200 OK$ref400Unknown name "$ref"$defs400Unknown name "$defs"additionalProperties400Unknown name "additionalProperties"oneOf200 OKanyOf/allOf/enum+constwere attempted but not conclusively captured in this run — treat those as untested.Raw error payloads
The message surfaced in the DSH UI (
Request contains an invalid argument.) is Gemini's generic wrapper; thedetails[]/ field-level reason above is what actually identifies the culprit.Why it breaks the whole session
DSH re-sends the complete tool catalog on every turn. As soon as one loaded tool carries
$ref,$defs, oradditionalProperties, the payload is rejected before inference — so the failure is constant, not content-dependent.In this environment the main contributor is the REA MCP server (
@deepseek-ai/dsh-mcp-client), whose schemas use$defs+$refheavily. However, removing that MCP server is not a full workaround, because some built-in tool schemas also emitadditionalProperties(e.g. theworkflowtool'sargsfield).Suggested fix
Either of these would resolve it:
Sanitize schemas on the Gemini path (preferred). Before building
functionDeclarations, walk each tool'sparametersand:$ref/$defs(dereference),additionalProperties,{type:"object", additionalProperties:true}fallback if dereferencing cannot converge (recursive schemas).Note:
0.2.1-rc.3contains no such sanitizer — symbol scan ofapp.asarforpruneSchema,sanitizeSchema,dereferenceSchema,resolveSchemaRefsreturned nothing.Expose per-provider tool filtering so a provider can exclude incompatible tools (e.g.
mcp__rea__*) without unloading the MCP server globally. The onlytoolFilterfound inapp.asarisContinuableSubagentDescriptorData.toolFilter?: ToolRestriction, which is sub-agent scoped and does not affect the outbound Gemini payload.Expected behavior
A Google Gemini model should be selectable in a session that has MCP tools mounted, with schemas downgraded to what the API accepts — or, at minimum, DSH should surface the field-level
details[]reason ("Unknown name$defs") instead of only the genericRequest contains an invalid argument., so users can tell a model/provider incompatibility apart from a bad API key or a network failure.中文摘要
现象:任何挂了复杂 MCP 工具的会话,切到 Google Gemini 线路后,每一条消息都返回
400 INVALID_ARGUMENT / Request contains an invalid argument.,与消息内容无关;切到 DeepSeek 线路即正常。根因:DSH 把工具的完整 JSON Schema 原样发给 Gemini,而 Gemini 的
functionDeclarations[].parameters只接受 OpenAPI 3.0 子集,遇到$ref、$defs、additionalProperties会直接Cannot find field拒绝。工具清单每轮都发,所以必然整场失败。已实测:无工具 / 扁平 schema /
oneOf→ 200;$ref/$defs/additionalProperties→ 400。建议:在 Gemini 请求路径上对 schema 做降级(解引用
$ref/$defs、删additionalProperties),或提供按 provider 过滤工具的能力。当前0.2.1-rc.3两者都没有。All reactions