wavetermdev/waveterm · error
failed to marshal input: %w
Error message
failed to marshal input: %w
What it means
parseTermGetScrollbackInput normalizes the tool's loosely-typed input (any) by round-tripping it through JSON: marshal to bytes, then unmarshal into TermGetScrollbackToolInput. This error wraps a failure of the json.Marshal step. In practice this is rare because the marshal target is the caller-provided value, but non-serializable values (channels, funcs, cyclic maps) or invalid values would trigger it.
Source
Thrown at pkg/aiusechat/tools_term.go:64
func parseTermGetScrollbackInput(input any) (*TermGetScrollbackToolInput, error) {
const (
DefaultCount = 200
MaxCount = 1000
)
result := &TermGetScrollbackToolInput{
LineStart: 0,
Count: 0,
}
if input == nil {
result.Count = DefaultCount
return result, nil
}
inputBytes, err := json.Marshal(input)
if err != nil {
return nil, fmt.Errorf("failed to marshal input: %w", err)
}
if err := json.Unmarshal(inputBytes, result); err != nil {
return nil, fmt.Errorf("failed to unmarshal input: %w", err)
}
if result.Count == 0 {
result.Count = DefaultCount
}
if result.Count < 0 {
return nil, fmt.Errorf("count must be positive")
}
result.Count = min(result.Count, MaxCount)
return result, nil
}View on GitHub (pinned to a4447c1563)
Solutions
- Inspect the wrapped error to identify the unsupported type (json.UnsupportedTypeError) or cycle (json.UnsupportedValueError)
- Ensure tool input is plain JSON-compatible data (strings, numbers, bools, maps, slices) before invoking the parser
- Build input from JSON-decoded arguments (map[string]any) as the tool framework does
- If constructing input in tests/harnesses, only use marshalable values
Example fix
// before
input := map[string]any{"widget_id": "b1", "count": someFunc} // not marshalable
parsed, err := parseTermGetScrollbackInput(input)
// after
input := map[string]any{"widget_id": "b1", "count": 100} // JSON-compatible
parsed, err := parseTermGetScrollbackInput(input) Defensive patterns
Strategy: validation
Validate before calling
func isJSONMarshallable(v any) error {
_, err := json.Marshal(v)
return err
}
if err := isJSONMarshallable(input); err != nil { return nil, err } Type guard
func isPlainJSONValue(v any) bool {
switch v.(type) {
case nil, bool, string, int, int64, float64, json.Number:
return true
case map[string]any:
for _, e := range v.(map[string]any) { if !isPlainJSONValue(e) { return false } }
return true
case []any:
for _, e := range v.([]any) { if !isPlainJSONValue(e) { return false } }
return true
default:
return false
}
} Prevention
- Only pass JSON-decoded tool arguments (map[string]any) into tool callbacks
- Never embed channels, funcs, or cyclic structures in tool input maps
- If building inputs in code, marshal them once yourself first to catch problems early
When it happens
Trigger: Calling term_get_scrollback's parse path with an input value that encoding/json cannot marshal — e.g. a map containing a channel, function, or cyclic reference instead of plain JSON-compatible data.
Common situations: Programmatic/preview invocations of the tool callback passing raw Go values rather than JSON-decoded tool arguments; custom tool harnesses injecting unsupported types; unsupported-type json.UnsupportedTypeError from a misbuilt input map.
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
- input is required
- invalid input format: %w
- failed to unmarshal input: %w
- missing zone file info for ${zoneId}:${fileName}
- cannot call ${methodName}: no web endpoint
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/6f0392d328c211b6.
Report an issue: GitHub.