wavetermdev/waveterm · error

error setting field %s: %w

Error message

error setting field %s: %w

What it means

MapToStruct matched a struct field by its JSON name and found a value in the input map, but setValue failed while coercing/storing it; this wrapper adds the field name for context via %w. The root cause is inside setValue — type mismatch, non-convertible types, or kind-specific set failures.

Source

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

		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)
			}
		}
	}

	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())
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Read the wrapped inner error to see the exact type conflict, then fix the source data or the struct field type
  2. Pre-normalize the map: convert string numbers to numbers (strconv) before calling MapToStruct
  3. Use flexible field types (json.Number, custom scalar types with UnmarshalJSON) for loose inputs
  4. Add per-field validation of the input map before conversion to catch bad values early

Example fix

// before
raw := map[string]any{"port": "8080"}
var cfg Config // Port int
err := utilfn.MapToStruct(raw, &cfg) // error setting field port: ...
// after
if s, ok := raw["port"].(string); ok {
    if n, cerr := strconv.Atoi(s); cerr == nil {
        raw["port"] = n
    }
}
err := utilfn.MapToStruct(raw, &cfg)
Defensive patterns

Strategy: validation

Validate before calling

// normalize common string->typed values before MapToStruct
for k, v := range in {
    if s, ok := v.(string); ok {
        if n, err := strconv.Atoi(s); err == nil { in[k] = n; continue }
        if b, err := strconv.ParseBool(s); err == nil { in[k] = b }
    }
}

Try / catch

if err := utilfn.MapToStruct(in, &cfg); err != nil {
    var fname string
    if strings.Contains(err.Error(), "error setting field ") {
        fmt.Sscanf(err.Error(), "error setting field %s", &fname)
        log.Printf("bad value for field %q: %v", fname, err)
    }
}

Prevention

When it happens

Trigger: Input map has "port": "8080" (string) for an int field with no convertible path handled, "tags": "a,b" for []string, a nested object for a non-struct field, or null/nil handling gaps — setValue's error is wrapped with the offending field name.

Common situations: JSON/YAML config files with values typed as strings by the parser being fed into typed structs; API payloads with numbers-as-strings; schema drift between producer and struct definition.

Related errors


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