wavetermdev/waveterm · error
input must be a struct or pointer to struct, got %v
Error message
input must be a struct or pointer to struct, got %v
What it means
StructToMap serializes a struct (or pointer to struct) into a map[string]any using json tags. It rejects any input whose underlying reflect.Kind is not struct after one level of pointer dereference, because there are no fields to iterate.
Source
Thrown at tsunami/util/marshal.go:57
if err := setValue(elem.Field(i), value); err != nil {
return fmt.Errorf("error setting field %s: %w", name, err)
}
}
}
return nil
}
func StructToMap(in any) (map[string]any, error) {
// Get value and handle pointer
val := reflect.ValueOf(in)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
// Check that we have a struct
if val.Kind() != reflect.Struct {
return nil, fmt.Errorf("input must be a struct or pointer to struct, got %v", val.Kind())
}
// Get type information
typ := val.Type()
out := make(map[string]any)
// 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)
out[name] = val.Field(i).Interface()
}View on GitHub (pinned to a4447c1563)
Solutions
- Ensure you pass a struct or a single-level pointer to a struct: util.StructToMap(&myStruct).
- Check for nil before calling: if ptr == nil { ... } — nil pointers cannot be converted.
- If you have a **T or interface{}, unwrap to the struct first with reflection or a type assertion.
Example fix
// before
out, err := util.StructToMap(cfgPtr) // cfgPtr is nil or *Config -> **Config
// after
if cfgPtr != nil {
out, err := util.StructToMap(*cfgPtr)
} Defensive patterns
Strategy: type-guard
Validate before calling
func canConvertToMap(in any) bool {
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
if v.IsNil() { return false }
v = v.Elem()
}
return v.Kind() == reflect.Struct
} Type guard
func isStructLike(in any) bool {
v := reflect.ValueOf(in)
for v.Kind() == reflect.Ptr {
if v.IsNil() { return false }
v = v.Elem()
}
return v.Kind() == reflect.Struct
} Try / catch
if !isStructLike(in) {
return nil, fmt.Errorf("StructToMap requires struct, got %T", in)
}
out, err := util.StructToMap(in)
if err != nil {
return nil, err
} Prevention
- Check for nil pointers before calling StructToMap
- Never pass **T; dereference once first
- Constrain generic helpers with interface{ constraints } or runtime kind checks
When it happens
Trigger: Calling util.StructToMap(x) where x is a map, slice, string, int, nil interface, a **T (double pointer), or a nil *T (Elem() of nil pointer yields an invalid value, not a struct).
Common situations: Passing a nil pointer after a failed lookup; passing already-converted map output back into StructToMap by mistake; generic helper code where the type parameter ends up being a non-struct.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- invalid number type %s
- 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
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/f0d527489f610658.
Report an issue: GitHub.