gohugoio/hugo · error
unable to cast %#v of type %T to []map[string]interface{}
Error message
unable to cast %#v of type %T to []map[string]interface{} What it means
hmaps.ToSliceStringMap converts an arbitrary value into []map[string]interface{}. It accepts []map[string]any, Params, map[string]any, or []any (keeping only map entries); every other concrete type hits the default case and returns this error with the value and its Go type. Hugo uses it where config or front matter must be a list of maps (e.g. lists of objects).
Source
Thrown at common/hmaps/maps.go:112
// ToSliceStringMap converts in to []map[string]interface{}.
func ToSliceStringMap(in any) ([]map[string]any, error) {
switch v := in.(type) {
case []map[string]any:
return v, nil
case Params:
return []map[string]any{v}, nil
case map[string]any:
return []map[string]any{v}, nil
case []any:
var s []map[string]any
for _, entry := range v {
if vv, ok := entry.(map[string]any); ok {
s = append(s, vv)
}
}
return s, nil
default:
return nil, fmt.Errorf("unable to cast %#v of type %T to []map[string]interface{}", in, in)
}
}
// LookupEqualFold finds key in m with case insensitive equality checks.
func LookupEqualFold[T any | string](m map[string]T, key string) (T, string, bool) {
if v, found := m[key]; found {
return v, key, true
}
for k, v := range m {
if strings.EqualFold(k, key) {
return v, k, true
}
}
var s T
return s, "", false
}
// MergeShallow merges src into dst, but only if the key does not already exist in dst.View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Fix the config/front matter shape: the value must be a list of maps (in YAML, a list of `key: value` blocks; in TOML, [[double-bracket]] tables).
- Print the offending value with `printf "%#v"` or `jsonify` to see its actual type, then adjust the source.
- If keys are non-string (old YAML), quote them or restructure so YAML produces map[string]interface{}.
Example fix
# before (front matter) resources: ["image.png", "doc.pdf"] # after resources: - src: image.png - src: doc.pdf
Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the value is a slice of maps before conversion
if _, ok := v.([]map[string]any); !ok {
if s, ok := v.([]any); ok { /* check each element is a map */ _ = s }
} Type guard
func isSliceOfMaps(v any) bool {
switch s := v.(type) {
case []map[string]any:
return true
case []any:
for _, e := range s {
if _, ok := e.(map[string]any); !ok { return false }
}
return len(s) > 0
}
return false
} Try / catch
m, err := hmaps.ToSliceStringMap(v)
if err != nil {
// value isn't a list of objects — report the actual type from the error
} Prevention
- Ensure YAML/TOML/JSON data files define a list of objects (e.g. `- name: x`), not a scalar or a single map.
- Check front-matter shape: a field expected to be a list of maps must not be a plain string.
- Probe with reflect.Kind or a type switch before calling map-conversion helpers.
When it happens
Trigger: Passing a scalar, a string, a []string, or a map with non-string keys where Hugo expects a slice of maps — e.g. a config section like `[[menu.main]]`-style structures, cascade lists, or template code calling this converter on a param that is a plain string or list of strings.
Common situations: YAML/TOML front matter or site config where a key expected to be a list of objects is written as a plain list of strings or a single string (e.g. `outputs` vs a list of tables); data files with map[interface{}]interface{} keys from older YAML; passing the wrong param to a function expecting map slices.
Related errors
- media type %q not found
- key %q not allowed in cascade config
- startLevel: %w
- failed to decode build config in front matter: %s%s
- failed to decode sitemap config in front matter: %s
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/5f99470d0f4648f2.json.
Report an issue: GitHub ↗.