{"record":{"id":"a3a30a15c0e3138d","repo":"siyuan-note/siyuan","slug":"tool-arguments-are-not-valid-json-w","errorCode":null,"errorMessage":"tool arguments are not valid JSON: %w","messagePattern":"tool arguments are not valid JSON: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/agent/tools.go","lineNumber":342,"sourceCode":"\t\treturn joined\n\t}\n\tif result.HasStructuredContent() {\n\t\tif data, err := json.Marshal(result.StructuredContent); err == nil {\n\t\t\treturn string(data)\n\t\t}\n\t}\n\treturn \"(empty result)\"\n}\n\n// parseToolArgs 在流结束后解析完整的工具参数，避免把损坏的 JSON 误报为缺少 schema 字段。\nfunc parseToolArgs(argsJSON string) (map[string]any, error) {\n\tif strings.TrimSpace(argsJSON) == \"\" {\n\t\treturn map[string]any{}, nil\n\t}\n\n\tvar args map[string]any\n\tif err := json.Unmarshal([]byte(argsJSON), &args); err != nil {\n\t\treturn nil, fmt.Errorf(\"tool arguments are not valid JSON: %w\", err)\n\t}\n\tif args == nil {\n\t\treturn nil, fmt.Errorf(\"tool arguments must be a JSON object\")\n\t}\n\treturn args, nil\n}\n","sourceCodeStart":324,"sourceCodeEnd":349,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/agent/tools.go#L324-L349","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nparseToolArgs(`{\"path\": \"/tmp/x\",}`) // trailing comma -> error\n\n// after\nargs, err := json.Marshal(map[string]any{\"path\": \"/tmp/x\"})\nparsed, err := parseToolArgs(string(args)) // always valid JSON","handlingStrategy":"validation","validationCode":"function isValidJSONArgs(s) {\n  const t = (s ?? \"\").trim();\n  if (t === \"\") return true; // parsed as empty args\n  if (t === \"null\") return false;\n  try { const v = JSON.parse(t); return v !== null && typeof v === \"object\" && !Array.isArray(v); } catch { return false; }\n}","typeGuard":"function isJSONObject(v) { return v !== null && typeof v === \"object\" && !Array.isArray(v); }","tryCatchPattern":"args, err := parseToolArgs(raw)\nif err != nil {\n    var jsonErr *json.SyntaxError\n    if errors.As(err, &jsonErr) {\n        log.Warnf(\"bad tool args at offset %d: %s\", jsonErr.Offset, raw)\n    }\n    return fmt.Errorf(\"retry with strict JSON: %w\", err)\n}","preventionTips":["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"],"tags":["json","llm-tools","parsing"],"backgroundTag":"json-parse-error","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}