Skip to content

Tools with array/object parameters fail when LLM sends stringified JSON #7512

@crottolo

Description

@crottolo

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():

  1. If validation fails with type mismatch, attempt to coerce string values
  2. For strings starting with [ or {: try JSON.parse()
  3. For numeric strings: convert with Number()
  4. For "true"/"false": convert to boolean
  5. Retry validation with coerced values
  6. 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
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions