-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Open
Description
Bug Description
Tools with typed parameters (array, object, number, boolean) fail with Zod validation error when the LLM sends the parameter as a string instead of the proper type.
Error Examples
Case 1: Array as string (Todowrite)
⚙ Todowrite [todos=[{"id": "1", "content": "Database: Migration", "status": "completed", "priority": "high"}, ...]]
Error: The Todowrite tool was called with invalid arguments: [
{
"expected": "array",
"code": "invalid_type",
"path": ["todos"],
"message": "Invalid input: expected array, received string"
}
]
Case 2: Number as string (Bash timeout)
⚙ Bash [command=pnpm build 2>&1 | head -100, description=Build project to verify i18n fixes, timeout=180000]
Error: The Bash tool was called with invalid arguments: [
{
"expected": "number",
"code": "invalid_type",
"path": ["timeout"],
"message": "Invalid input: expected number, received string"
}
]
Root Cause
LLMs sometimes serialize typed parameters as strings:
{ "todos": "[{...}]" }instead of{ "todos": [{...}] }{ "timeout": "180000" }instead of{ "timeout": 180000 }{ "enabled": "true" }instead of{ "enabled": true }
Affected Tools
| Tool | Parameter | Type |
|---|---|---|
| Todowrite | todos | array |
| Question | questions | array |
| Bash | timeout | number |
| Webfetch | timeout | number |
| Websearch | numResults | number |
| LSP tools | line, character | number |
| Edit | replaceAll | boolean |
| Multiedit | replaceAll | boolean |
Proposed Fix
Add automatic coercion in Tool.define():
- If validation fails with type mismatch, attempt to coerce string values
- For strings starting with
[or{: tryJSON.parse() - For numeric strings: convert with
Number() - For "true"/"false": convert to boolean
- Retry validation with coerced values
- Backward compatible: if coercion fails, throw original error
Environment
- OpenCode version: 1.1.8
- All providers affected (Anthropic, OpenAI, Google, etc.)
Metadata
Metadata
Assignees
Labels
No labels