siyuan-note/siyuan · error
tool arguments are not valid JSON: %w
Error message
tool arguments are not valid JSON: %w
What it means
parseToolArgs in kernel/agent/tools.go wraps a json.Unmarshal failure when converting an LLM tool-call arguments string into a map[string]any. The agent passes whatever JSON text the model produced for tool arguments, and this error means that text is not syntactically valid JSON at all. The underlying encoding/json error is preserved via %w so callers can inspect the exact parse failure.
Source
Thrown at kernel/agent/tools.go:342
return joined
}
if result.HasStructuredContent() {
if data, err := json.Marshal(result.StructuredContent); err == nil {
return string(data)
}
}
return "(empty result)"
}
// parseToolArgs 在流结束后解析完整的工具参数,避免把损坏的 JSON 误报为缺少 schema 字段。
func parseToolArgs(argsJSON string) (map[string]any, error) {
if strings.TrimSpace(argsJSON) == "" {
return map[string]any{}, nil
}
var args map[string]any
if err := json.Unmarshal([]byte(argsJSON), &args); err != nil {
return nil, fmt.Errorf("tool arguments are not valid JSON: %w", err)
}
if args == nil {
return nil, fmt.Errorf("tool arguments must be a JSON object")
}
return args, nil
}
View on GitHub (pinned to 8641553a1f)
Solutions
- Log the raw argsJSON string alongside the wrapped error and fix the source that produced the malformed JSON (usually the model prompt or the code assembling the arguments).
- If the model regularly emits slightly-off JSON, add a repair/normalization pass (e.g. strip trailing commas, ensure quoting) or instruct the model more strictly to output strict JSON.
- In code building arguments programmatically, marshal with json.Marshal instead of string concatenation so the payload is always valid JSON.
- Check that streaming assembly of the arguments field is complete before calling parseToolArgs (wait for the finish event).
Example fix
// before
parseToolArgs(`{"path": "/tmp/x",}`) // trailing comma -> error
// after
args, err := json.Marshal(map[string]any{"path": "/tmp/x"})
parsed, err := parseToolArgs(string(args)) // always valid JSON Defensive patterns
Strategy: validation
Validate before calling
function isValidJSONArgs(s) {
const t = (s ?? "").trim();
if (t === "") return true; // parsed as empty args
if (t === "null") return false;
try { const v = JSON.parse(t); return v !== null && typeof v === "object" && !Array.isArray(v); } catch { return false; }
} Type guard
function isJSONObject(v) { return v !== null && typeof v === "object" && !Array.isArray(v); } Try / catch
args, err := parseToolArgs(raw)
if err != nil {
var jsonErr *json.SyntaxError
if errors.As(err, &jsonErr) {
log.Warnf("bad tool args at offset %d: %s", jsonErr.Offset, raw)
}
return fmt.Errorf("retry with strict JSON: %w", err)
} Prevention
- Build arguments with json.Marshal, never string concatenation
- Instruct the model to emit strict JSON with no comments or trailing commas
- Wait for stream completion before parsing the arguments field
- Log raw argsJSON on failure for debugging
When it happens
Trigger: Calling parseToolArgs (directly or via executeCapability) with an argsJSON string that json.Unmarshal rejects: truncated output, single quotes instead of double quotes, unescaped newlines/quotes inside strings, trailing commas, or non-JSON text such as plain prose produced by the model in the arguments field. An empty/whitespace-only string is fine (returns empty map), so only malformed non-empty input triggers this.
Common situations: An LLM emits tool arguments with comments or JavaScript object syntax instead of JSON; streaming output is cut off mid-object; a prompt template interpolates unescaped quotes into the arguments field; integration tests feed hand-written malformed JSON.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- tool arguments must be a JSON object
- %w: %v
- unmarshal AI editor actions failed: %w
- unmarshal master password migration failed: %w
- unmarshal inline styles failed: %w
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/a3a30a15c0e3138d.
Report an issue: GitHub.