googleapis/mcp-toolbox · error
failed to marshal result: %w
Error message
failed to marshal result: %w
What it means
After a successful tool run, runInvoke pretty-prints the result with json.MarshalIndent. This error fires if the tool's returned result cannot be serialized to JSON — typically a result containing values Go's encoding/json cannot handle (channels, funcs, cyclic structures, or unsupported custom types) (cmd/internal/invoke/command.go:158-164).
Source
Thrown at cmd/internal/invoke/command.go:161
return errMsg
}
if requiresAuth {
errMsg := fmt.Errorf("client authorization is not supported")
opts.Logger.ErrorContext(ctx, errMsg.Error())
return errMsg
}
result, err := tool.Invoke(ctx, src, parsedParams, "")
if err != nil {
errMsg := fmt.Errorf("tool execution failed: %w", err)
opts.Logger.ErrorContext(ctx, errMsg.Error())
return errMsg
}
// Print Result
output, err := json.MarshalIndent(result, "", " ")
if err != nil {
errMsg := fmt.Errorf("failed to marshal result: %w", err)
opts.Logger.ErrorContext(ctx, errMsg.Error())
return errMsg
}
fmt.Fprintln(opts.IOStreams.Out, string(output))
return nil
}
View on GitHub (pinned to 8cc6e09de2)
Solutions
- Inspect the tool implementation's Invoke return value and ensure it contains only JSON-serializable types.
- For custom tools, convert unsupported fields (time, big numbers, byte slices) to strings or json.RawMessage before returning.
- If it's a built-in tool, report/upgrade: this indicates a bug in that tool kind's result shape; try a newer toolbox version.
- File an issue with the tool kind and result data if a stock tool reproduces it.
Example fix
// before (custom tool)
func (t *myTool) Invoke(...) (any, error) {
return map[string]any{"created": someCustomTimeType{}}, nil // unserializable
}
// after
func (t *myTool) Invoke(...) (any, error) {
return map[string]any{"created": time.Now().UTC().Format(time.RFC3339)}, nil
} Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure a tool result is JSON-marshalable before relying on CLI output:
func isJSONSafe(v any) bool {
_, err := json.Marshal(v)
return err == nil
} Type guard
func isJSONSerializable(v any) (string, bool) {
b, err := json.Marshal(v)
if err != nil { return "", false }
return string(b), true
} Try / catch
// When scripting around the CLI, treat any non-zero exit as marshal/other failure and fall back to raw server invocation:
out, err := exec.Command("toolbox", "invoke", tool, params).CombinedOutput()
if err != nil {
log.Fatalf("invoke failed (possibly non-JSON-serializable result): %s", out)
} Prevention
- In custom tool Invoke implementations, return only JSON-safe types (string, number, bool, slice, map[string]any, struct).
- Avoid cycles and non-string map keys in returned data.
- Prefer json.RawMessage for pre-encoded payloads.
- Update toolbox if a stock tool kind reproduces the error — it's likely a serialization bug.
When it happens
Trigger: `toolbox invoke <tool>` where the invoked tool kind returns a result object that fails JSON marshaling: a custom/primitive tool returning unserializable data (e.g. non-UTF8 bytes mishandled, maps with non-string keys of unsupported types, cycles).
Common situations: Using a custom tool (via the SDK) whose Invoke returns a struct with unexported cyclic pointers or non-JSON-safe types; a tool returning map[customType]any results; rarely, driver row values wrapped in unsupported types.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- params must be a valid JSON string: %w
- operation finished with error but could not marshal error ob
- failed to unmarshal operation bytes: %w
- failed to marshal request: %w
- failed to unmarshal cluster JSON: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/fdc3357954c81347.
Report an issue: GitHub.