wavetermdev/waveterm · error

out parameter must be a pointer, got %v

Error message

out parameter must be a pointer, got %v

What it means

MapToStruct uses reflection to copy a map[string]any into a struct, but reflection can only write through the out parameter if it is a pointer. This guard fires when out is a struct value (or any non-pointer), because writing to it would modify a copy and be lost. The error names the actual reflect.Kind received.

Source

Thrown at pkg/util/utilfn/marshal.go:61

// does a mapstructure using "json" tags
func DoMapStructure(out any, input any) error {
	dconfig := &mapstructure.DecoderConfig{
		Result:  out,
		TagName: "json",
	}
	decoder, err := mapstructure.NewDecoder(dconfig)
	if err != nil {
		return err
	}
	return decoder.Decode(input)
}

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

View on GitHub (pinned to a4447c1563)

Solutions

  1. Pass a pointer to the destination struct: MapToStruct(m, &cfg)
  2. If the value is addressable already, take its address before the call
  3. In generic/helper wrappers, require T any with a *T argument or reflect-check and return a clear compile-time-friendly API
  4. Add the guard message to your lint/test expectations so regressions fail fast

Example fix

// before
var cfg Config
err := utilfn.MapToStruct(raw, cfg) // out parameter must be a pointer, got struct
// after
var cfg Config
err := utilfn.MapToStruct(raw, &cfg)
Defensive patterns

Strategy: validation

Validate before calling

func checkOutPtr(out any) error {
    if out == nil { return errors.New("out is nil") }
    if reflect.ValueOf(out).Kind() != reflect.Ptr {
        return fmt.Errorf("out must be a pointer, got %T", out)
    }
    return nil
}

Type guard

func isPtrToStruct(out any) bool {
    v := reflect.ValueOf(out)
    return v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct
}

Try / catch

if err := utilfn.MapToStruct(m, out); err != nil {
    if strings.Contains(err.Error(), "must be a pointer") {
        // fix call site: pass &dest
    }
}

Prevention

When it happens

Trigger: Calling MapToStruct(m, myStruct) passing a struct value instead of &myStruct; passing a map, slice, or interface holding a non-pointer; passing an untyped nil as out.

Common situations: Copy-paste from StructToMap call sites (which take values); forgetting the & when the destination is a local variable; wrapping generic decode helpers that accept any.

Related errors


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