siyuan-note/siyuan · error
tool arguments must be a JSON object
Error message
tool arguments must be a JSON object
What it means
After a successful json.Unmarshal, parseToolArgs checks that the result is a non-nil map. JSON text like `null` or `"string"` unmarshals without error into a nil map (or fails type conversion), so this error rejects arguments that are valid JSON but not a JSON object. Tool arguments must be a key/value object for the capability executor to look up parameters.
Source
Thrown at kernel/agent/tools.go:345
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
- Ensure the tool-call arguments field is serialized as a JSON object `{...}`, even when empty: `{}` instead of `null`.
- For no-parameter tools, have callers pass `{}` explicitly; parseToolArgs also returns an empty map for empty strings.
- Sanitize upstream input: if argsJSON == "null" (after trim), replace with "{}" before parsing if the tool tolerates empty args.
Example fix
// before
parseToolArgs("null") // error: must be a JSON object
// after
if strings.TrimSpace(argsJSON) == "null" {
argsJSON = "{}"
}
parsed, err := parseToolArgs(argsJSON) Defensive patterns
Strategy: validation
Validate before calling
function ensureObjectArgs(s) {
const t = (s ?? "").trim();
if (t === "" || t === "null") return "{}";
const v = JSON.parse(t);
if (typeof v !== "object" || v === null || Array.isArray(v)) throw new Error("tool arguments must be a JSON object");
return t;
} Type guard
func isJSONObjectArgs(raw string) bool {
var m map[string]any
return json.Unmarshal([]byte(raw), &m) == nil && m != nil
} Try / catch
args, err := parseToolArgs(raw)
if err != nil {
if err.Error() == "tool arguments must be a JSON object" {
args = map[string]any{} // degrade to empty args if the tool has no required params
}
} Prevention
- Serialize no-argument tool calls as {} not null
- Always keep tool schemas declaring type: object
- Normalize null arguments to {} before calling the kernel
When it happens
Trigger: Calling parseToolArgs with argsJSON equal to `null`, or any JSON scalar/array that unmarshals into a nil map[string]any (e.g. arrays actually fail unmarshal into map, but `null` succeeds with nil). The classic trigger is a model emitting `null` as the arguments field.
Common situations: An LLM fills in `null` for arguments when a tool takes no parameters; a caller passes an already-decoded nil map serialized back to string; a test fixture uses `null` as arguments.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- invalid session data
- tool arguments are not valid JSON: %w
- invalid null bazaar index
- invalid bazaar repository: %s
- invalid marketplace package manifest
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/58407e760b0d1210.
Report an issue: GitHub.