{"record":{"id":"58407e760b0d1210","repo":"siyuan-note/siyuan","slug":"tool-arguments-must-be-a-json-object","errorCode":null,"errorMessage":"tool arguments must be a JSON object","messagePattern":"tool arguments must be a JSON object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/agent/tools.go","lineNumber":345,"sourceCode":"\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":327,"sourceCodeEnd":349,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/agent/tools.go#L327-L349","documentation":"parseToolArgs rejects arguments that unmarshal successfully into a JSON null (args == nil after Unmarshal of a non-empty input). Tool arguments must be a JSON object; literal \"null\" is not acceptable even though it is valid JSON.","triggerScenarios":"The model emits the literal string \"null\" as tool_call function arguments instead of \"{}\" or an object — json.Unmarshal yields a nil map, triggering this branch.","commonSituations":"Models with poor tool-calling training emitting \"null\" for no-argument tools, adapters normalizing empty arguments to null before forwarding, hand-crafted requests to the agent API passing arguments: \"null\".","solutions":["Send \"{}\" instead of \"null\" for tools that take no arguments","Fix or replace the adapter that converts empty arguments to JSON null","In the agent loop, feed this IsError result back to the model so it re-emits an object","If you control call construction, default empty arguments to an empty object before invoking"],"exampleFix":"// before\narguments = \"null\"\n// after\narguments = \"{}\"","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(argsJSON) == \"\" || argsJSON == \"null\" {\n    argsJSON = \"{}\"\n}","typeGuard":"func isJSONObjectArgs(s string) bool {\n    var m map[string]any\n    return json.Unmarshal([]byte(s), &m) == nil && m != nil\n}","tryCatchPattern":"args, err := parseToolArgs(tc.Function.Arguments)\nif err != nil {\n    return executedToolResult{Text: \"invalid capability arguments: \" + err.Error(), IsError: true}\n}","preventionTips":["Default no-argument tools to \"{}\" instead of \"null\"","Sanitize null arguments at adapter boundaries","Feed the error back to the model so it re-emits an object"],"tags":["ai","json","tool-calling","validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}