wavetermdev/waveterm · error
failed to marshal input: %w
Error message
failed to marshal input: %w
What it means
This error wraps json.Marshal failure when serializing the tool's input argument before POSTing it to the Tsunami widget's /api/config endpoint. json.Marshal fails only for values JSON cannot represent (channels, funcs, cycles, or unsupported types). The underlying marshal error is preserved via %w.
Source
Thrown at pkg/aiusechat/tools_tsunami.go:98
}
func makeTsunamiPostCallback(status *blockcontroller.BlockControllerRuntimeStatus, apiPath string) func(any, *uctypes.UIMessageDataToolUse) (any, error) {
return func(input any, toolUseData *uctypes.UIMessageDataToolUse) (any, error) {
if status.TsunamiPort == 0 {
return nil, fmt.Errorf("tsunami port not available")
}
url := fmt.Sprintf("http://localhost:%d%s", status.TsunamiPort, apiPath)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
var reqBody []byte
var err error
if input != nil {
reqBody, err = json.Marshal(input)
if err != nil {
return nil, fmt.Errorf("failed to marshal input: %w", err)
}
}
req, err := http.NewRequestWithContext(ctx, "POST", url, strings.NewReader(string(reqBody)))
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to make request to tsunami: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("tsunami returned status %d", resp.StatusCode)
}View on GitHub (pinned to a4447c1563)
Solutions
- Read the wrapped error to identify the offending type, then ensure the input passed to the tool callback is JSON-compatible (plain maps, slices, strings, numbers, bools).
- Marshal the input yourself with json.Marshal (or utilfn.ReUnmarshal) before invoking the callback to catch the problem early with a clearer stack.
- If input comes from a non-JSON source, convert it to a JSON-safe representation first.
- For complex config values, register MarshalJSON on the custom type so it serializes correctly.
Example fix
// before: callback(map[string]any{"cb": func() {}}) fails with 'json: unsupported type: func()'; // after: callback(map[string]any{"refreshInterval": 30}) with JSON-safe input only Defensive patterns
Strategy: validation
Validate before calling
if _, err := json.Marshal(input); err != nil { return fmt.Errorf("tool input is not JSON-serializable: %w", err) } Type guard
func isJSONSafe(v any) bool { _, err := json.Marshal(v); return err == nil } Try / catch
out, err := callback(input, toolUseData); if err != nil && strings.Contains(err.Error(), "failed to marshal input") { /* sanitize input to a JSON-safe map and retry once */ } Prevention
- Pass only JSON-decoded values (maps, slices, strings, numbers, bools) into tool callbacks.
- Pre-marshal inputs in tests to catch unsupported types early.
- Avoid funcs/channels/cyclic references in config objects.
- Use utilfn.ReUnmarshal to normalize inputs before invoking callbacks.
When it happens
Trigger: Calling tsunami_setconfig with an input value containing non-JSON-serializable data (e.g. a map holding a func or channel, cyclic structures) - though inputs normally arrive as decoded JSON from the model, hand-crafted or programmatic callers can pass arbitrary any values.
Common situations: Programmatic/tool-harness callers passing Go-native values with unsupported types instead of plain JSON-compatible maps; custom tool runners injecting config objects containing cyclic references or unserializable field 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
- marshaling directory listing for %s: %w
- failed to marshal JSON: %v
- marshaling json: %w
- formatting version info: %v
- json encoding: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/d29d6764215333dc.
Report an issue: GitHub.