wavetermdev/waveterm · error
out parameter must be a pointer to struct, got pointer to %v
Error message
out parameter must be a pointer to struct, got pointer to %v
What it means
After confirming out is a pointer, MapToStruct checks that the pointed-to value is a struct, because field-by-field reflection only works on struct kinds. A pointer to a map, slice, string, or other non-struct kind yields "out parameter must be a pointer to struct, got pointer to %v".
Source
Thrown at tsunami/util/marshal.go:22
package util
import (
"fmt"
"reflect"
"strings"
)
func MapToStruct(in map[string]any, out any) error {
// Check that out is a pointer
outValue := reflect.ValueOf(out)
if outValue.Kind() != reflect.Ptr {
return fmt.Errorf("out parameter must be a pointer, got %v", outValue.Kind())
}
// Get the struct it points to
elem := outValue.Elem()
if elem.Kind() != reflect.Struct {
return fmt.Errorf("out parameter must be a pointer to struct, got pointer to %v", elem.Kind())
}
// Get type information
typ := elem.Type()
// For each field in the struct
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
// Skip unexported fields
if !field.IsExported() {
continue
}
name := getJSONName(field)
if value, ok := in[name]; ok {
if err := setValue(elem.Field(i), value); err != nil {
return fmt.Errorf("error setting field %s: %w", name, err)View on GitHub (pinned to a4447c1563)
Solutions
- Declare the out target as a struct (or pointer to struct) whose json tags match the map keys
- If the target is a map, skip MapToStruct and index the map directly
- For slices, write a dedicated loop or change the call site to decode into a struct
Example fix
// before
var out map[string]any
util.MapToStruct(m, &out) // pointer to map, not struct
// after
type result struct {
Name string `json:"name"`
Size int `json:"size"`
}
var out result
if err := util.MapToStruct(m, &out); err != nil { return err } Defensive patterns
Strategy: validation
Validate before calling
rv := reflect.ValueOf(out)
if rv.Kind() == reflect.Ptr && rv.Elem().Kind() != reflect.Struct {
return fmt.Errorf("target must be *struct, got *%v", rv.Elem().Kind())
} Type guard
func isStructPtr(v any) bool {
rv := reflect.ValueOf(v)
return rv.Kind() == reflect.Ptr && rv.Elem().Kind() == reflect.Struct
} Try / catch
if err := util.MapToStruct(m, &result); err != nil {
return fmt.Errorf("decode failed (need *struct target): %w", err)
} Prevention
- Decode into a struct with json tags matching the map keys, never into a map/slice
- Index maps directly instead of routing them through MapToStruct
- Add a startup test that decodes a sample map into every decode target struct
When it happens
Trigger: MapToStruct(m, &someMap) with someMap of type map[string]any; MapToStruct(m, &someSlice); MapToStruct(m, &str).
Common situations: Trying to reuse MapToStruct as a generic map-to-value decoder for maps/slices; passing &out where out is already map[string]any from a JSON decode; mismatch between the component function's return type and the caller's decode target.
Related errors
- out parameter must be a pointer, got %v
- out parameter must be a pointer to struct, got pointer to %v
- error setting field %s: %w
- input must be a struct or pointer to struct, got %v
- cannot set value of type %v to field of type %v
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/137fe4945b9b5ae5.
Report an issue: GitHub.