siyuan-note/siyuan · error

tool arguments must be a JSON object

Error message

tool arguments must be a JSON object

What it means

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.

Solutions

  1. Send "{}" instead of "null" for tools that take no arguments
  2. Fix or replace the adapter that converts empty arguments to JSON null
  3. In the agent loop, feed this IsError result back to the model so it re-emits an object
  4. If you control call construction, default empty arguments to an empty object before invoking

Example fix

// before
arguments = "null"
// after
arguments = "{}"
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(argsJSON) == "" || argsJSON == "null" {
    argsJSON = "{}"
}

Type guard

func isJSONObjectArgs(s string) bool {
    var m map[string]any
    return json.Unmarshal([]byte(s), &m) == nil && m != nil
}

Try / catch

args, err := parseToolArgs(tc.Function.Arguments)
if err != nil {
    return executedToolResult{Text: "invalid capability arguments: " + err.Error(), IsError: true}
}

Prevention

When it happens

Trigger: 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.

Common situations: 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".

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/58407e760b0d1210. Report an issue: GitHub.

Appendix: 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 9f775e8a12)