wavetermdev/waveterm · error
cannot set value of type %v to field of type %v
Error message
cannot set value of type %v to field of type %v
What it means
setValue is MapToStruct's field-assignment helper. After trying direct assignment and ConvertibleTo-based conversion, it gives up if the input value's type still cannot be stored in the field type, reporting both types. Non-convertible cases include string→slice, map→struct, and different named types without convertible underlying kinds.
Source
Thrown at pkg/util/utilfn/marshal.go:165
// Check if types are assignable
if valueRef.Type().AssignableTo(field.Type()) {
field.Set(valueRef)
return nil
}
// If field is pointer and value isn't already a pointer, try address
if field.Kind() == reflect.Ptr && valueRef.Kind() != reflect.Ptr {
return setValue(field, valueRef.Addr().Interface())
}
// Try conversion if types are convertible
if valueRef.Type().ConvertibleTo(field.Type()) {
field.Set(valueRef.Convert(field.Type()))
return nil
}
return fmt.Errorf("cannot set value of type %v to field of type %v", valueRef.Type(), field.Type())
}
// DecodeDataURL decodes a data URL and returns the mimetype and raw data bytes
func DecodeDataURL(dataURL string) (mimeType string, data []byte, err error) {
if !strings.HasPrefix(dataURL, "data:") {
return "", nil, fmt.Errorf("invalid data URL: must start with 'data:'")
}
parts := strings.SplitN(dataURL, ",", 2)
if len(parts) != 2 {
return "", nil, fmt.Errorf("invalid data URL format: missing comma separator")
}
header := parts[0]
dataStr := parts[1]
// Parse mimetype from header: "data:text/plain;base64" -> "text/plain"
headerWithoutPrefix := strings.TrimPrefix(header, "data:")View on GitHub (pinned to a4447c1563)
Solutions
- Convert the value in the caller to the exact field type before calling MapToStruct (strconv, json.Unmarshal into the target, etc.)
- Implement UnmarshalJSON on custom field types if the data shape is fixed but the representation is loose
- Use encoding/json's map→struct path (json.Marshal then json.Unmarshal) which handles more coercions, if performance allows
- Align the struct field type with the real data type (e.g. use json.Number or string fields for stringly-typed sources)
Example fix
// before
raw := map[string]any{"tags": "a,b"} // Tags []string
var cfg Config
utilfn.MapToStruct(raw, &cfg) // cannot set value of type string to field of type []string
// after
raw["tags"] = strings.Split("a,b", ",")
utilfn.MapToStruct(raw, &cfg) // ok Defensive patterns
Strategy: validation
Validate before calling
func canSet(field reflect.Value, val any) bool {
v := reflect.ValueOf(val)
return v.Type().AssignableTo(field.Type()) || v.Type().ConvertibleTo(field.Type())
} Try / catch
if err := utilfn.MapToStruct(in, &cfg); err != nil {
if strings.Contains(err.Error(), "cannot set value of type") {
// coerce the offending value manually and retry
}
} Prevention
- Match value types to field types before conversion (strconv/json round-trip)
- Use json.Number or custom types with UnmarshalJSON for loose data
- Prefer encoding/json for map→struct when heavy coercion is needed
When it happens
Trigger: Setting []string field from a string value; bool field from "true" string (strconv not attempted); time.Time field from an int64 timestamp; named type mismatch where ConvertibleTo is false (e.g. func/map kinds).
Common situations: Loosely typed config formats (YAML/TOML parsers yielding map[string]any of strings) feeding strictly typed structs; version drift where a struct field changed type; hand-built maps with JSON-ish values of wrong types.
Related errors
- error setting field %s: %w
- error setting field %s: %w
- out parameter must be a pointer, got %v
- out parameter must be a pointer to struct, got pointer to %v
- 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/d841423d829b8472.
Report an issue: GitHub.