github/copilot-sdk · error
failed to unmarshal arguments into %T
Error message
failed to unmarshal arguments into %T: %w
What it means
After marshaling, the arguments are unmarshaled into the tool's typed parameter struct T. If the arguments do not match the struct's field types/requirements, json.Unmarshal fails and the error is wrapped with this message including the target type. It means the caller supplied arguments that don't fit the tool's declared parameter schema.
Solutions
- Read the wrapped unmarshal error: it names the offending field and expected type
- Compare the sent arguments against the tool's input schema and correct types/field names
- Ensure required fields are present and JSON types match the Go struct (e.g. no stringified numbers)
- If the schema changed, update clients to the new argument shape
Example fix
// before
{"count": "3"} // string where int expected
// after
{"count": 3} // correct JSON type for params.Count int Defensive patterns
Strategy: validation
Validate before calling
// validate arguments against the tool schema before invoking
jsonBytes, _ := json.Marshal(args)
var probe MyToolParams
if err := json.Unmarshal(jsonBytes, &probe); err != nil { /* reject early */ } Try / catch
// Go
res, err := tool.Invoke(inv)
var typeErr *json.UnmarshalTypeError
if err != nil && errors.As(err, &typeErr) {
// typeErr.Field names the mismatched argument field
} Prevention
- Publish and follow each tool's input schema
- Send correct JSON types (numbers as numbers, not strings)
- Update client argument shapes when tool schemas change
When it happens
Trigger: Calling a tool with a missing required field, wrong JSON type (string where number expected), or a value failing a custom UnmarshalJSON — anything that makes the round-trip into T fail.
Common situations: LLM or client sending malformed tool arguments; API surface changed (renamed/retyped field) while callers send the old shape; numbers sent as strings; nested objects not matching struct tags.
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
- failed to unmarshal response
- failed to marshal arguments
- failed to serialize result
- invalid hook input
- marshal elicitation schema property
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/e2a02f005b391d94.
Report an issue: GitHub.
Appendix: source
Thrown at go/definetool.go:56
Parameters: schema,
Handler: createTypedHandler(handler),
}
}
// createTypedHandler wraps a typed handler function into the standard ToolHandler signature.
func createTypedHandler[T any, U any](handler func(T, ToolInvocation) (U, error)) ToolHandler {
return func(inv ToolInvocation) (ToolResult, error) {
var params T
// Convert arguments to typed struct via JSON round-trip
// Arguments is already map[string]any from JSON-RPC parsing
jsonBytes, err := json.Marshal(inv.Arguments)
if err != nil {
return ToolResult{}, fmt.Errorf("failed to marshal arguments: %w", err)
}
if err := json.Unmarshal(jsonBytes, ¶ms); err != nil {
return ToolResult{}, fmt.Errorf("failed to unmarshal arguments into %T: %w", params, err)
}
result, err := handler(params, inv)
if err != nil {
return ToolResult{}, err
}
return normalizeResult(result)
}
}
// normalizeResult converts any value to a ToolResult.
// Strings pass through directly, ToolResult passes through, and other types
// are JSON-serialized.
func normalizeResult(result any) (ToolResult, error) {
if result == nil {
return ToolResult{
TextResultForLLM: "",View on GitHub (pinned to cd8cf15dc3)