gohugoio/hugo · error
unmarshal: %T not supported
Error message
unmarshal: %T not supported
What it means
Thrown by Decoder.UnmarshalStringTo (parser/metadecoders/decoder.go:138) when the target type 'typ' is not one of the supported cases (string, map[string]any, hmaps.Params, []any, bool, int, int64, float64). The %T names the unsupported type. This function dispatches on the concrete Go type of the destination, so an arbitrary struct or pointer triggers the default branch.
Solutions
- Pass one of the supported target types: string, map[string]any, hmaps.Params, []any, bool, int, int64, or float64.
- For decoding into arbitrary structs, use Decoder.UnmarshalTo(data, format, &myStruct) instead of UnmarshalStringTo.
- If a custom collection type is needed, decode into map[string]any first then convert.
Example fix
// before var s MyStruct v, err := dec.UnmarshalStringTo(raw, &s) // after v, err := dec.UnmarshalTo([]byte(raw), metadecoders.JSON, &s)
Defensive patterns
Strategy: type-guard
Validate before calling
// Only pass supported target types to UnmarshalStringTo.
func isSupportedStringTarget(typ any) bool {
switch typ.(type) {
case string, map[string]any, hmaps.Params, []any, bool, int, int64, float64:
return true
}
return false
} Type guard
func isSupportedStringTarget(typ any) bool {
switch typ.(type) {
case string, map[string]any, hmaps.Params, []any, bool, int, int64, float64:
return true
}
return false
} Try / catch
v, err := dec.UnmarshalStringTo(raw, target)
if err != nil {
return fmt.Errorf("cannot unmarshal string into target: %w", err)
} Prevention
- Use UnmarshalTo for struct decoding; reserve UnmarshalStringTo for the eight supported scalar/collection types.
- Document the supported set near call sites.
When it happens
Trigger: Calling UnmarshalStringTo(data, someStruct{}) or UnmarshalStringTo(data, &myType{}) where the target is not one of the eight supported scalar/collection types; passing a custom type alias that does not match any case.
Common situations: Programmatic misuse of the metadecoders API by plugin/theme authors; passing a struct pointer expecting reflection-based decoding (use UnmarshalTo for that).
Related errors
- cannot unmarshal CSV into %T
- cannot unmarshal CSV into %T: invalid targetType: expected…
- invalid targetType: expected either slice or map, received
- unmarshal of format is not supported
- XML root element ' ' must be a map/object, got %T
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/6c6fddb8d8669dbd.
Report an issue: GitHub.
Appendix: source
Thrown at parser/metadecoders/decoder.go:138
switch typ.(type) {
case string:
return data, nil
case map[string]any, hmaps.Params:
format := d.FormatFromContentString(data)
return d.UnmarshalToMap([]byte(data), format)
case []any:
// A standalone slice. Let YAML handle it.
return d.Unmarshal([]byte(data), YAML)
case bool:
return cast.ToBoolE(data)
case int:
return cast.ToIntE(data)
case int64:
return cast.ToInt64E(data)
case float64:
return cast.ToFloat64E(data)
default:
return nil, fmt.Errorf("unmarshal: %T not supported", typ)
}
}
// Unmarshal will unmarshall data in format f into an interface{}.
// This is what's needed for Hugo's /data handling.
func (d Decoder) Unmarshal(data []byte, f Format) (any, error) {
if len(data) == 0 {
switch f {
case CSV:
switch d.TargetType {
case "map":
return make(map[string]any), nil
case "slice":
return make([][]string, 0), nil
default:
return nil, fmt.Errorf("invalid targetType: expected either slice or map, received %s", d.TargetType)
}
default:View on GitHub (pinned to 52c9bd7908)