{"record":{"id":"0fcc1e004c6ef0cd","repo":"github/copilot-sdk","slug":"failed-to-marshal-arguments-w","errorCode":null,"errorMessage":"failed to marshal arguments: %w","messagePattern":"failed to marshal arguments: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/definetool.go","lineNumber":52,"sourceCode":"\n\treturn Tool{\n\t\tName:        name,\n\t\tDescription: description,\n\t\tParameters:  schema,\n\t\tHandler:     createTypedHandler(handler),\n\t}\n}\n\n// createTypedHandler wraps a typed handler function into the standard ToolHandler signature.\nfunc createTypedHandler[T any, U any](handler func(T, ToolInvocation) (U, error)) ToolHandler {\n\treturn func(inv ToolInvocation) (ToolResult, error) {\n\t\tvar params T\n\n\t\t// Convert arguments to typed struct via JSON round-trip\n\t\t// Arguments is already map[string]any from JSON-RPC parsing\n\t\tjsonBytes, err := json.Marshal(inv.Arguments)\n\t\tif err != nil {\n\t\t\treturn ToolResult{}, fmt.Errorf(\"failed to marshal arguments: %w\", err)\n\t\t}\n\n\t\tif err := json.Unmarshal(jsonBytes, &params); err != nil {\n\t\t\treturn ToolResult{}, fmt.Errorf(\"failed to unmarshal arguments into %T: %w\", params, err)\n\t\t}\n\n\t\tresult, err := handler(params, inv)\n\t\tif err != nil {\n\t\t\treturn ToolResult{}, err\n\t\t}\n\n\t\treturn normalizeResult(result)\n\t}\n}\n\n// normalizeResult converts any value to a ToolResult.\n// Strings pass through directly, ToolResult passes through, and other types\n// are JSON-serialized.","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/go/definetool.go#L34-L70","documentation":"The typed tool wrapper converts the JSON-RPC invocation's Arguments (map[string]any) into the tool's typed params struct via a JSON round-trip. If json.Marshal on the arguments map fails, this error is returned. In practice this is rare because the arguments already came from JSON parsing; it guards against values that cannot be serialized (e.g. channels, funcs, or NaN injected programmatically).","triggerScenarios":"An invocation whose Arguments map contains values unsupported by encoding/json (func, channel, complex types) — typically only possible when a caller constructs the invocation in Go code rather than receiving it over JSON-RPC.","commonSituations":"Unit tests or in-process tool invocation passing non-JSON-serializable argument values; programmatic wiring of a tool handler with malformed Arguments.","solutions":["Inspect the Arguments map at the call site for non-JSON-serializable values","Construct invocations only with JSON-safe types (string, number, bool, nil, slices, maps)","Validate/sanitize arguments before invoking the tool","The wrapped err names the unsupported type — fix that field specifically"],"exampleFix":"// before\ninv.Arguments[\"callback\"] = func() {} // not JSON-serializable\n// after\n// only pass JSON-representable values:\ninv.Arguments[\"mode\"] = \"sync\"","handlingStrategy":"validation","validationCode":"// ensure all argument values are JSON-serializable before invoking\njson.Marshal(inv.Arguments) // do a pre-flight marshal in tests","typeGuard":"// Go: reject values encoding/json cannot serialize\nfunc jsonSafe(v any) bool {\n\tb, err := json.Marshal(v)\n\treturn err == nil && b != nil\n}","tryCatchPattern":"// Go\nres, err := tool.Invoke(inv)\nif err != nil && strings.Contains(err.Error(), \"failed to marshal arguments\") {\n\t// fix the invocation's Arguments to contain only JSON-safe values\n}","preventionTips":["Only construct Arguments with JSON-representable types","Add unit tests that round-trip invocations through JSON","Never inject funcs/channels into Arguments maps"],"tags":["json","mcp","arguments"],"backgroundTag":"json-marshal-failed","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}