{"record":{"id":"9ac43518ae672564","repo":"wavetermdev/waveterm","slug":"error-setting-field-s-w-9ac435","errorCode":null,"errorMessage":"error setting field %s: %w","messagePattern":"error setting field (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tsunami/util/marshal.go","lineNumber":40,"sourceCode":"\t\treturn fmt.Errorf(\"out parameter must be a pointer to struct, got pointer to %v\", elem.Kind())\n\t}\n\n\t// Get type information\n\ttyp := elem.Type()\n\n\t// For each field in the struct\n\tfor i := 0; i < typ.NumField(); i++ {\n\t\tfield := typ.Field(i)\n\n\t\t// Skip unexported fields\n\t\tif !field.IsExported() {\n\t\t\tcontinue\n\t\t}\n\n\t\tname := getJSONName(field)\n\t\tif value, ok := in[name]; ok {\n\t\t\tif err := setValue(elem.Field(i), value); err != nil {\n\t\t\t\treturn fmt.Errorf(\"error setting field %s: %w\", name, err)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc StructToMap(in any) (map[string]any, error) {\n\t// Get value and handle pointer\n\tval := reflect.ValueOf(in)\n\tif val.Kind() == reflect.Ptr {\n\t\tval = val.Elem()\n\t}\n\n\t// Check that we have a struct\n\tif val.Kind() != reflect.Struct {\n\t\treturn nil, fmt.Errorf(\"input must be a struct or pointer to struct, got %v\", val.Kind())\n\t}","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/tsunami/util/marshal.go#L22-L58","documentation":"MapToStruct copies values from a map[string]any into struct fields via reflection. This error wraps the underlying setValue failure (type mismatch, unassignable/convertible types) with the JSON field name that failed, so you know exactly which key in the map could not be mapped into the destination struct.","triggerScenarios":"Call util.MapToStruct(in, &outStruct) where in contains a key matching a struct field's json tag (or Go field name), but the value's dynamic type is not assignable or convertible to the field's type (e.g. string into int, []any into []string, nested map into a non-struct field).","commonSituations":"Decoding loosely-typed config (YAML/TOML parsed as map[string]any) into typed structs; JSON numbers arriving as float64 into int fields after a numeric-type change; schema drift where an API returns a string but the struct expects a slice or struct.","solutions":["Read the wrapped field name in the error and fix the value's type in the map (or use encoding/json.Unmarshal, which has richer unmarshaling rules) so it matches the struct field type.","Change the struct field type to match the incoming data (e.g. int -> float64, string -> []string) or add a custom type with UnmarshalJSON.","Pre-normalize the map before calling MapToStruct (coerce numbers with FromFloat64-style helpers, convert nested maps)."],"exampleFix":"// before\nvar cfg Config\nerr := util.MapToStruct(map[string]any{\"port\": \"8080\"}, &cfg) // error setting field port\n// after\nport, _ := strconv.Atoi(\"8080\")\nerr := util.MapToStruct(map[string]any{\"port\": port}, &cfg)","handlingStrategy":"try-catch","validationCode":"func validateMapping(in map[string]any, out any) error {\n    v := reflect.ValueOf(out).Elem().Type()\n    for i := 0; i < v.NumField(); i++ {\n        name := v.Field(i).Name\n        if tag := v.Field(i).Tag.Get(\"json\"); tag != \"\" && tag != \"-\" {\n            name = strings.Split(tag, \",\")[0]\n        }\n        if val, ok := in[name]; ok && val != nil {\n            if reflect.TypeOf(val) != reflect.TypeOf(v.Field(i)) {\n                return fmt.Errorf(\"field %s: value type %T may not map to %s\", name, val, v.Field(i).Type)\n            }\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := util.MapToStruct(in, &cfg); err != nil {\n    var fieldErr string\n    if _, scanErr := fmt.Sscanf(err.Error(), \"error setting field %s\", &fieldErr); scanErr == nil {\n        log.Printf(\"bad value for field %q, using defaults\", fieldErr)\n    }\n    return fmt.Errorf(\"config mapping failed: %w\", err)\n}","preventionTips":["Prefer encoding/json.Unmarshal which coerces more JSON shapes, unless you need map-to-struct specifically","Keep map values sourced from the same schema version as the struct definition","Write a round-trip test: StructToMap -> MapToStruct -> compare, to catch type drift early"],"tags":["reflection","type-mismatch","marshaling","go"],"backgroundTag":"struct-field-type-mismatch","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}