gohugoio/hugo · error
unmarshal: %T not supported
Error message
unmarshal: %T not supported
What it means
Decoder.UnmarshalStringTo converts a string into a value of the same type as the provided prototype `typ`, but it only supports string, map (map[string]any / maps.Params), []any, bool, int, int64, and float64. Any other prototype type falls through to the default case and returns this error with the Go type name, because Hugo has no defined conversion for it.
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 8a468df065)
Solutions
- Change the target/default value to one of the supported types — use a plain map, []any, string, bool, int, int64, or float64 as the prototype.
- In templates, unmarshal to a generic value first (`transform.Unmarshal $str`) and then cast (`int`, `float`, `time.AsTime`) instead of expecting a typed result directly.
- If it appears after a Hugo upgrade, check the release notes for changes to the config/param whose type is named in the %T output and adjust its declared type.
Example fix
{{/* before: expecting a typed value Hugo can't produce */}}
{{ $v := transform.Unmarshal $s }}{{/* target type unsupported upstream */}}
{{/* after: unmarshal generically, then cast */}}
{{ $v := transform.Unmarshal $s }}
{{ $n := int $v }} Defensive patterns
Strategy: type-guard
Type guard
// Only pass string or []byte data to Unmarshal
func unmarshalable(v any) bool {
switch v.(type) {
case string, []byte:
return true
}
return false
} Try / catch
if err != nil && strings.Contains(err.Error(), "not supported") {
// the input was already-decoded data or a wrong type; convert to string first
} Prevention
- In templates, only call `transform.Unmarshal` on strings/resources, not on maps/slices that are already decoded
- Guard with `{{ if reflect.IsMap . }}` (already decoded) before attempting Unmarshal
- Convert numeric or other types to string explicitly before unmarshalling
When it happens
Trigger: Internal callers (e.g. `transform.Unmarshal` with a typed default, front matter/param coercion paths) passing a prototype whose dynamic type is outside the supported set — e.g. a time.Time, a struct, uint, float32, or a typed slice like []string instead of []any.
Common situations: Template authors hitting it indirectly via `transform.Unmarshal` or param handling when a default/target value has an unexpected type; Hugo version changes shifting which types flow into this coercion; custom output/data pipelines producing typed values Hugo tries to unmarshal a string into.
Related errors
- symdiff: failed to convert value: %w
- the math.Abs function requires a numeric argument
- Ceil operator can't be used with non-float value
- Floor operator can't be used with non-float value
- Log operator can't be used with non integer or float value
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/6c6fddb8d8669dbd.json.
Report an issue: GitHub ↗.