You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Gemini requests fail with 400 exclusiveMinimum — numeric constraints only stripped for gpt-oss models #37
Gemini requests routed through the Antigravity endpoint fail with HTTP 400 when the request includes tools, because OpenCode's built-in tool schemas contain JSON-Schema numeric constraints (e.g. exclusiveMinimum: 0 on glob/greplimit fields) and the plugin forwards them unchanged. Google's Cloud Code endpoint strictly validates the protobuf payload and rejects unknown fields.
Repro
opencode run --model google/antigravity-gemini-3.8-flash "Reply with exactly this word and nothing else: OK"
Response (Status 400):
Invalid JSON payload received. Unknown name "exclusiveMinimum" at 'request.tools[0].function_declarations[1].parameters.properties[3].value': Cannot find field.
Invalid JSON payload received. Unknown name "exclusiveMinimum" at 'request.tools[0].function_declarations[2].parameters.properties[5].value': Cannot find field.
Invalid JSON payload received. Unknown name "exclusiveMinimum" at 'request.tools[0].function_declarations[8].parameters.properties[2].value': Cannot find field.
Debug info: Requested Model antigravity-gemini-3.8-flash, Effective Model gemini-3.8-flash-medium, Project aicode-consumers, Endpoint https://daily-cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse. Same failure on antigravity-gemini-3.1-pro.
And in toGeminiSchema, numeric constraints (exclusiveMinimum, minimum, maximum, minLength, …) are only moved to the description hint when options.moveNumericConstraintsToDescription is truthy — otherwise they fall through to result[key] = value and are sent verbatim. So every non-gpt-oss Gemini request carrying tools with numeric constraints gets a 400 from Google.
Expected
Strip (or move to description) numeric schema constraints for Gemini models too, not just gpt-oss-* — the machinery in toGeminiSchema already supports it via the flag.
Workaround verified
Disabling tools for the model ("tools": {"*": false} on a test agent) makes the same request succeed and return a correct response, confirming auth/quota/model routing are all fine and this is purely a schema-sanitization gap.
Additional findings from real-world testing (same setup as above):
1. A second, broader error class from MCP tool schemas. With MCP servers attached (TUI session), Gemini requests fail with a different 400 family:
GenerateContentRequest.tools[0].function_declarations[1].parameters.properties[fields].items: field predicate failed: $type == Type.ARRAY
GenerateContentRequest.tools[0].function_declarations[1].parameters.properties[fields].any_of[0].items: missing field.
GenerateContentRequest.tools[0].function_declarations[16].parameters.properties[size].properties: only allowed for OBJECT type
GenerateContentRequest.tools[0].function_declarations[18].parameters.properties[pages].items: field predicate failed: $type == Type.ARRAY
GenerateContentRequest.tools[0].function_declarations[18].parameters.properties[pages].any_of[0].items: missing field.
GenerateContentRequest.tools[0].function_declarations[20].parameters.properties[files].items: field predicate failed: $type == Type.ARRAY
GenerateContentRequest.tools[0].function_declarations[20].parameters.properties[files].any_of[0].items: missing field.
So it's not just numeric constraints: anyOf wrappers, stray items on non-ARRAY types, and properties on non-OBJECT types all pass through unsanitized on this path. A full strict-mode schema normalizer (strip/convert anyOf/oneOf, drop items unless type: ARRAY, drop properties unless type: OBJECT, handle numeric constraints) is needed for the Gemini-via-Antigravity path, like the official AI SDK google provider does.
2. provider.<id>.models.<mid>.tools is silently dropped by OpenCode v2 config parsing. Setting per-model tool disables (e.g. provider.google.models.antigravity-gemini-3.8-flash.tools = {glob: false, ...}) has no effect — opencode debug config shows the model entry arriving as {}. Users currently cannot work around this per model.
3. Verified workaround: agent-level explicit tool disables DO work. An agent with "tools": {"glob": false, "grep": false, "webfetch": false} makes antigravity-gemini-3.8-flash respond correctly (remaining core tools accepted). Note: "tools": {} does NOT disable anything (empty = all enabled), and project-level agents require a service restart to register.
Activity
CultureDigitali commentedon Oct 13, 2026
Additional findings from real-world testing (same setup as above):
1. A second, broader error class from MCP tool schemas. With MCP servers attached (TUI session), Gemini requests fail with a different 400 family:
So it's not just numeric constraints:
anyOfwrappers, strayitemson non-ARRAY types, andpropertieson non-OBJECT types all pass through unsanitized on this path. A full strict-mode schema normalizer (strip/convertanyOf/oneOf, dropitemsunlesstype: ARRAY, droppropertiesunlesstype: OBJECT, handle numeric constraints) is needed for the Gemini-via-Antigravity path, like the official AI SDK google provider does.2.
provider.<id>.models.<mid>.toolsis silently dropped by OpenCode v2 config parsing. Setting per-model tool disables (e.g.provider.google.models.antigravity-gemini-3.8-flash.tools = {glob: false, ...}) has no effect —opencode debug configshows the model entry arriving as{}. Users currently cannot work around this per model.3. Verified workaround: agent-level explicit tool disables DO work. An agent with
"tools": {"glob": false, "grep": false, "webfetch": false}makesantigravity-gemini-3.8-flashrespond correctly (remaining core tools accepted). Note:"tools": {}does NOT disable anything (empty = all enabled), and project-level agents require a service restart to register.