Tencent/WeKnora · error
args must be a string or an array of strings: %w
Error message
args must be a string or an array of strings: %w
What it means
SkillExecuteTool's UnmarshalJSON wraps a json.Unmarshal failure when the raw Args payload is neither a JSON array of strings nor a JSON string. The tool accepts argv arrays (or a stringified array) and rejects any other JSON shape, wrapping the underlying json error with %w so it can be errors.Is/As inspected.
Source
Thrown at internal/agent/tools/skill_execute.go:116
return err
}
i.SkillName = raw.SkillName
i.ScriptPath = raw.ScriptPath
i.Input = raw.Input
i.Args = nil
if len(raw.Args) == 0 || string(raw.Args) == "null" {
return nil
}
if err := json.Unmarshal(raw.Args, &i.Args); err == nil {
return nil
}
var argsString string
if err := json.Unmarshal(raw.Args, &argsString); err != nil {
return fmt.Errorf("args must be a string or an array of strings: %w", err)
}
// Some providers emit the array as a stringified JSON payload
// (e.g. "[\"--project-name\",\"X\"]"). Treat that as an array first so the
// model's intent is preserved; strings.Fields would otherwise split the
// brackets/quotes into garbage tokens and the script would see nonsense argv.
if err := json.Unmarshal([]byte(argsString), &i.Args); err == nil {
return nil
}
// A plain string is interpreted as a conventional space-separated command
// line. The tool schema continues to advertise []string, so well-formed
// calls are unaffected; this is only a compatibility fallback for model
// output.
i.Args = strings.Fields(argsString)
return nil
}
View on GitHub (pinned to 988cbb0330)
Solutions
- Change the Args payload to a JSON array of strings, e.g. ["--flag","value"].
- If the provider only supports objects, map the object to an argv array before unmarshalling.
- Inspect the wrapped error with errors.As(*json.UnmarshalTypeError) to identify the offending shape.
Example fix
// before
{"tool": "skill_execute", "args": {"project-name": "X"}}
// after
{"tool": "skill_execute", "args": ["--project-name", "X"]} Defensive patterns
Strategy: validation
Validate before calling
switch v := any(raw.Args).(type) {
case []any, string:
// acceptable shapes
default:
return fmt.Errorf("args must be a string or array of strings, got %T", v)
} Type guard
func validArgsShape(raw json.RawMessage) bool {
var arr []string
var s string
return json.Unmarshal(raw, &arr) == nil || json.Unmarshal(raw, &s) == nil
} Try / catch
if err := json.Unmarshal(payload, &input); err != nil {
var jerr *json.UnmarshalTypeError
if errors.As(err, &jerr) && strings.Contains(err.Error(), "args must be a string or an array of strings") {
// convert object args to argv array and retry
}
} Prevention
- Emit tool arguments as a JSON array of strings (argv style)
- Convert provider object-style arguments to arrays before dispatch
- Log the raw Args JSON when unmarshalling fails to spot shape mismatches early
When it happens
Trigger: A provider emits Args as a JSON object (e.g. {"flag":"value"}), a number, boolean, or null, and the wrapped json.Unmarshal into []string and then into string both fail.
Common situations: Model tool-calls that pass named key/value arguments instead of an argv array; hand-written tool payloads using an unsupported shape; provider SDKs serializing arguments as objects.
Related errors
- logical operator %s requires an array of conditions
- failed to unmarshal condition at index %d: %w
- unmarshal page: %w
- unmarshal database: %w
- unmarshal data_sources: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/54ddecda2a094b07.
Report an issue: GitHub.