wavetermdev/waveterm · error

failed to marshal input: %w

Error message

failed to marshal input: %w

What it means

This error wraps a json.Marshal failure while converting the generic tool input (any) to bytes as part of re-unmarshaling it into the typed WebNavigateToolInput struct. Because the input normally originates from decoded JSON this is rare, but programmatic callers passing non-serializable values (channels, funcs, cyclic data) will hit it. The cause is preserved via %w.

Source

Thrown at pkg/aiusechat/tools_web.go:32

	"github.com/wavetermdev/waveterm/pkg/wcore"
	"github.com/wavetermdev/waveterm/pkg/wstore"
)

type WebNavigateToolInput struct {
	WidgetId string `json:"widget_id"`
	Url      string `json:"url"`
}

func parseWebNavigateInput(input any) (*WebNavigateToolInput, error) {
	result := &WebNavigateToolInput{}

	if input == nil {
		return nil, fmt.Errorf("input is required")
	}

	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.WidgetId == "" {
		return nil, fmt.Errorf("widget_id is required")
	}

	if result.Url == "" {
		return nil, fmt.Errorf("url is required")
	}

	return result, nil
}

func GetWebNavigateToolDefinition(tabId string) uctypes.ToolDefinition {

View on GitHub (pinned to a4447c1563)

Solutions

  1. Inspect the wrapped error for the unsupported type, then pass JSON-compatible input (map[string]any or a struct with JSON tags).
  2. Pre-marshal the input yourself to validate it before calling the callback.
  3. Convert non-JSON types (e.g. func/chan values) to string or other serializable representations first.
  4. If the input originates from the model, this should never fire - check for harness corruption of the arguments.

Example fix

// before: callback(map[string]any{"onReady": func() {}}) fails with 'unsupported type: func()'; // after: callback(map[string]any{"widget_id": "AB12CD34", "url": "https://example.com"}) with JSON-safe values only
Defensive patterns

Strategy: validation

Validate before calling

if _, err := json.Marshal(input); err != nil { return fmt.Errorf("web_navigate input not serializable: %w", err) }

Type guard

func isStringMap(v any) bool { _, ok := v.(map[string]any); return ok }

Try / catch

parsed, err := parseWebNavigateInput(input); if err != nil && strings.Contains(err.Error(), "failed to marshal input") { /* input contained unsupported types; convert to JSON-safe map and retry */ }

Prevention

When it happens

Trigger: Invoking the web_navigate callback with an input any that cannot be marshaled - cyclic structures, unsupported types (func, chan), or values with failing custom marshalers.

Common situations: Test harnesses or programmatic tool runners passing Go-native objects with unsupported field types; plugin code injecting rich objects instead of plain maps/JSON values into tool callbacks.

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


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/dee71be5ba320225. Report an issue: GitHub.