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 converts a struct to map[string]any via reflection; after dereferencing one pointer level, the value must be a struct kind. This error reports the actual kind when the input is a map, slice, primitive, or a double pointer whose dereference is still not a struct.
Source
Thrown at pkg/util/utilfn/marshal.go:102
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
- Pass the struct itself or a single pointer to it: StructToMap(&cfg) or StructToMap(cfg)
- If you have a map already, you don't need conversion — use it directly or call MapToStruct for the opposite direction
- Constrain generics with [T any] + a runtime struct check, or [T struct] style patterns where possible
- Dereference extra pointer layers before the call if your data comes from *T producers
Example fix
// before
m, err := utilfn.StructToMap(rawMap) // input must be a struct or pointer to struct, got map
// after
type Config struct{ Name string `json:"name"` }
var cfg Config
m, err := utilfn.StructToMap(&cfg) Defensive patterns
Strategy: type-guard
Validate before calling
func isStructOrPtr(v any) bool {
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Ptr { rv = rv.Elem() }
return rv.Kind() == reflect.Struct
} Type guard
func isStructOrPtr(v any) bool {
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Ptr { rv = rv.Elem() }
return rv.Kind() == reflect.Struct
} Try / catch
m, err := utilfn.StructToMap(v)
if err != nil && strings.Contains(err.Error(), "must be a struct") {
// wrong helper or wrong type: check %T of v
} Prevention
- Use StructToMap only for structs; use MapToStruct for maps
- Avoid passing **T or primitives into reflection helpers
- Constrain generic helpers to struct types
When it happens
Trigger: Calling StructToMap(someMap) (wrong direction — that's MapToStruct's job); passing a *[]T or **T; passing nil interface; passing a primitive like an int or string.
Common situations: Swapping the two helper functions by mistake in serialization glue; generic code where the type parameter isn't constrained to structs; passing results of another reflection-based call straight back in.
Related errors
- out parameter must be a pointer to struct, got pointer to %v
- out parameter must be a pointer, got %v
- error setting field %s: %w
- cannot set value of type %v to field of type %v
- out parameter must be a pointer, got %v
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/dd7f7cd87ad686a1.
Report an issue: GitHub.