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
~ Updating todos...
Error: The todowrite tool was called with invalid arguments: [
{
"expected": "array",
"code": "invalid_type",
"path": [
"todos"
],
"message": "Invalid input: expected array, received string"
}
].
Please rewrite the input so it satisfies the expected schema.
Still reproduces on opencode 1.17.11, and a heads-up for anyone landing here: the tool.execute.before → JSON.parse(todos) plugin workaround posted earlier in this thread no longer works on current opencode.
I instrumented a bare version of that workaround (only tool.execute.before, nothing else) and confirmed with markers that for a stringified todos the hook never fires — the call is rejected at argument validation beforeexecute.before runs:
EXECUTE_BEFORE todosType=string : 0 # stringified calls never reach execute.before
EXECUTE_BEFORE todosType=object : 1 # only native-array calls do
Why it used to work and now doesn't: the error format in this thread changed from the Zod style (code: "invalid_type", "Invalid input: expected array, received string") to SchemaError(Expected array, got "<string>"). Tool-argument validation moved from Zod to Effect Schema, and it now runs ahead oftool.execute.before, so no plugin can repair the args in time.
For completeness, none of the plugin hooks can fix this on 1.17.11:
tool.definition overriding a built-in tool's parameters/jsonSchema is not used for validation (verified by instrumentation: the override's validate is never called for the built-in todowrite).
tool.execute.before runs after validation (markers above).
A shadow/custom tool can't replace todowrite because the SDK exposes only GET /session/{id}/todo (no write API), so a plugin can't update todo state.
Trigger (detailed writeup in #34652): Claude via the native Anthropic provider intermittently emits nested array tool args as JSON strings; OpenAI/function-calling models don't. It is intermittent and not size-gated — even an empty array [] has been observed arriving as "[]".
Suggested fix: coerce a stringified tool-arg back to the expected type during tool-arg decoding (scoped strictly so it can't mask unrelated errors), or let plugin tool.definition overrides drive validation for built-in tools so the ecosystem can patch provider quirks without a core change.
Quick confirming update from #34652: retested today on the latest opencode (1.17.12) with a newer Claude model (claude-sonnet-5, not the Opus I originally tested) — still reproduces. Same intermittent, non-size-gated pattern (3 consecutive todowrite calls in a fresh session: 7-item payload succeeded, 8-item and even a 1-item payload both failed with the same SchemaError).
So this isn't an Opus-only quirk and it isn't fixed in the current release. Full evidence and the suggested fix are in #34652.
Activity
github-actions commentedon Jan 27, 2026
This issue might be a duplicate of existing issues. Please check:
todosparameter is received as a stringified array instead of an actual arrayFeel free to ignore if none of these address your specific case.
eliawk commentedon Mar 18, 2026
same issue
leohidalgo commentedon Mar 21, 2026
Workaround
.opencode/plugins/todo-fix-plugin.tsedikid commentedon Jul 1, 2026
Still reproduces on opencode
1.17.11, and a heads-up for anyone landing here: thetool.execute.before→JSON.parse(todos)plugin workaround posted earlier in this thread no longer works on current opencode.I instrumented a bare version of that workaround (only
tool.execute.before, nothing else) and confirmed with markers that for a stringifiedtodosthe hook never fires — the call is rejected at argument validation beforeexecute.beforeruns:Why it used to work and now doesn't: the error format in this thread changed from the Zod style (
code: "invalid_type","Invalid input: expected array, received string") toSchemaError(Expected array, got "<string>"). Tool-argument validation moved from Zod to Effect Schema, and it now runs ahead oftool.execute.before, so no plugin can repair the args in time.For completeness, none of the plugin hooks can fix this on 1.17.11:
tool.definitionoverriding a built-in tool'sparameters/jsonSchemais not used for validation (verified by instrumentation: the override'svalidateis never called for the built-intodowrite).tool.execute.beforeruns after validation (markers above).todowritebecause the SDK exposes onlyGET /session/{id}/todo(no write API), so a plugin can't update todo state.Trigger (detailed writeup in #34652): Claude via the native Anthropic provider intermittently emits nested array tool args as JSON strings; OpenAI/function-calling models don't. It is intermittent and not size-gated — even an empty array
[]has been observed arriving as"[]".Suggested fix: coerce a stringified tool-arg back to the expected type during tool-arg decoding (scoped strictly so it can't mask unrelated errors), or let plugin
tool.definitionoverrides drive validation for built-in tools so the ecosystem can patch provider quirks without a core change.edikid commentedon Jul 1, 2026
Quick confirming update from #34652: retested today on the latest opencode (
1.17.12) with a newer Claude model (claude-sonnet-5, not the Opus I originally tested) — still reproduces. Same intermittent, non-size-gated pattern (3 consecutivetodowritecalls in a fresh session: 7-item payload succeeded, 8-item and even a 1-item payload both failed with the sameSchemaError).So this isn't an Opus-only quirk and it isn't fixed in the current release. Full evidence and the suggested fix are in #34652.
github-actions commentedon Aug 31, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.