[PR #7513] fix(opencode): coerce stringified JSON arrays/objects in tool parameters #12420

Open
opened 2026-02-16 18:17:20 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/7513

State: open
Merged: No


Fixes #7512

Problem

LLMs sometimes send tool parameters as strings instead of proper typed values:

{ "todos": "[{...}]" }    // string instead of array
{ "timeout": "180000" }   // string instead of number  
{ "enabled": "true" }     // string instead of boolean

This causes Zod validation to fail with expected X, received string.

Solution

Added automatic coercion in Tool.define():

  1. First attempt normal validation with safeParse
  2. If fails with type error, coerce string values:
    • [ or { prefix → JSON.parse() for arrays/objects
    • Numeric string → Number() for numbers
    • "true"/"false" → boolean conversion
  3. Retry validation with coerced values
  4. If still fails, throw original error (backward compatible)

Verification

Tested all affected tools:

✅ Bash (timeout: number)
✅ Todowrite (todos: array)
✅ Webfetch (timeout: number)
✅ Websearch (numResults: number)
✅ LSP tools (line, character: number)
✅ Read (offset, limit: number)
✅ Normal typed values still work unchanged

Scope

  • 10+ tools affected: Bash, Todowrite, Question, Webfetch, Websearch, LSP, Edit, Multiedit, etc.
  • All providers: Anthropic, OpenAI, Google, etc.
  • Backward compatible: Yes
**Original Pull Request:** https://github.com/anomalyco/opencode/pull/7513 **State:** open **Merged:** No --- Fixes #7512 ## Problem LLMs sometimes send tool parameters as strings instead of proper typed values: ``` { "todos": "[{...}]" } // string instead of array { "timeout": "180000" } // string instead of number { "enabled": "true" } // string instead of boolean ``` This causes Zod validation to fail with `expected X, received string`. ## Solution Added automatic coercion in `Tool.define()`: 1. First attempt normal validation with `safeParse` 2. If fails with type error, coerce string values: - `[` or `{` prefix → `JSON.parse()` for arrays/objects - Numeric string → `Number()` for numbers - `"true"`/`"false"` → boolean conversion 3. Retry validation with coerced values 4. If still fails, throw original error (backward compatible) ## Verification Tested all affected tools: ``` ✅ Bash (timeout: number) ✅ Todowrite (todos: array) ✅ Webfetch (timeout: number) ✅ Websearch (numResults: number) ✅ LSP tools (line, character: number) ✅ Read (offset, limit: number) ✅ Normal typed values still work unchanged ``` ## Scope - **10+ tools affected**: Bash, Todowrite, Question, Webfetch, Websearch, LSP, Edit, Multiedit, etc. - **All providers**: Anthropic, OpenAI, Google, etc. - **Backward compatible**: Yes
yindo added the pull-request label 2026-02-16 18:17:20 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#12420