fix: prevent Gemini 400 errors for empty properties and custom-only tools#319
fix: prevent Gemini 400 errors for empty properties and custom-only tools#319m2m6vrm5fp-source wants to merge 1 commit intoNoeFabris:devfrom
Conversation
…ools
1. Add placeholder for empty OBJECT properties in toGeminiSchema()
- Gemini rejects properties: {} with 400 Bad Request
2. Create function from custom before custom is deleted
- Prevents schema loss when tool only has 'custom' format
3. Pass schemas through toGeminiSchema() in wrapToolsAsFunctionDeclarations()
- Ensures all schemas get the empty properties fix
WalkthroughChanges to Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 🧹 Recent nitpick comments
📜 Recent review detailsConfiguration used: Repository UI Review profile: CHILL Plan: Pro Cache: Disabled due to data retention organization setting Knowledge base: Disabled due to data retention organization setting 📒 Files selected for processing (1)
🧰 Additional context used🧬 Code graph analysis (1)src/plugin/transform/gemini.ts (3)
🔇 Additional comments (9)
✏️ Tip: You can disable this entire section by setting Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile OverviewGreptile SummaryThis PR fixes three related issues causing 400 Bad Request errors when using Gemini models with OpenCode/OhMyOpenCode. Problems Fixed1. Empty properties object rejection (lines 139-152)
2. Schema loss for custom-only tools (lines 371-378)
3. Schema transformation bypass in wrapper (lines 584-589, 625)
Changes Summary
The fixes ensure all tool schemas are Gemini-compatible before being sent to the API, preventing 400 errors. Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Client as OpenCode/OhMyOpenCode
participant Transform as applyGeminiTransforms
participant Normalize as normalizeGeminiTools
participant Wrap as wrapToolsAsFunctionDeclarations
participant Schema as toGeminiSchema
participant Gemini as Gemini API
Client->>Transform: Request with tools
Transform->>Normalize: Normalize tool formats
Note over Normalize: For each tool
Normalize->>Schema: Transform schema (line 325)
Schema->>Schema: Convert types to uppercase
Schema->>Schema: Remove unsupported fields
alt Empty properties detected
Schema->>Schema: Add _placeholder property (lines 139-152)
end
Schema-->>Normalize: Transformed schema
alt Tool has custom but no function
Normalize->>Normalize: Create function from custom (lines 371-378)
end
Normalize->>Normalize: Delete custom wrapper (line 394)
Normalize-->>Transform: Normalized tools
Transform->>Wrap: Wrap in functionDeclarations
Note over Wrap: For each tool
Wrap->>Schema: Transform parameters (lines 584, 625)
alt Empty properties in fallback
Schema->>Schema: Add _placeholder to fallback schema
end
Schema-->>Wrap: Gemini-compatible parameters
Wrap->>Wrap: Build functionDeclarations array
Wrap-->>Transform: Wrapped tools
Transform-->>Client: Transformed request
Client->>Gemini: Send request with valid schemas
Gemini-->>Client: Success (no 400 errors)
|
| name, | ||
| description, | ||
| parameters: schema, | ||
| parameters: toGeminiSchema(schema) as Record<string, unknown>, |
There was a problem hiding this comment.
check that test at gemini.test.ts:1087 still passes - it expects { type: "OBJECT", properties: {} } to remain unchanged, but this will now add the _placeholder property via toGeminiSchema()
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugin/transform/gemini.ts
Line: 625:625
Comment:
check that test at `gemini.test.ts:1087` still passes - it expects `{ type: "OBJECT", properties: {} }` to remain unchanged, but this will now add the `_placeholder` property via `toGeminiSchema()`
How can I resolve this? If you propose a fix, please make it concise.| description: "Placeholder parameter. Always pass true.", | ||
| }, | ||
| }; | ||
| result.required = ["_placeholder"]; |
There was a problem hiding this comment.
unconditionally overwrites any existing required array - though unlikely with empty properties, consider preserving existing required items if they exist
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugin/transform/gemini.ts
Line: 151:151
Comment:
unconditionally overwrites any existing `required` array - though unlikely with empty properties, consider preserving existing required items if they exist
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.
Summary
Fixes 400 Bad Request errors when using tools with OpenCode/OhMyOpenCode and Gemini models.
Problems Fixed
1. Gemini rejects empty properties object
Tools with
properties: {}(liketodoread) cause 400 Bad Request because Gemini's strict protobuf validation rejects empty properties.Fix: Add placeholder property when properties object is empty in
toGeminiSchema().2. Schema loss when tool has 'custom' but no 'function'
When a tool only has 'custom' format (no 'function'), the schema was being set on 'custom.input_schema' but then 'custom' was deleted, leaving the tool with no schema.
Fix: Create 'function' from 'custom' before 'custom' is deleted.
3. wrapToolsAsFunctionDeclarations bypasses toGeminiSchema
Schemas extracted in
wrapToolsAsFunctionDeclarationswere not being transformed throughtoGeminiSchema(), causing empty properties to slip through.Fix: Call
toGeminiSchema()on all extracted schemas.Testing
Tested with oh-my-opencode using Gemini 3 Pro via Antigravity:
todoreadtool (no parameters) now works