gohugoio/hugo · error
grouping not supported for type %T %T
Error message
grouping not supported for type %T %T
What it means
`group` only works on collections whose element type implements Hugo's internal `collections.Grouper` interface — in practice, only Pages. Hugo tries the collection itself, then a new empty slice of its element type, and if neither is a Grouper it reports both Go types via %T. Grouping arbitrary slices, maps, or strings is unsupported.
Source
Thrown at tpl/collections/collections.go:327
// Group groups a set of items by the given key.
// This is currently only supported for Pages.
func (ns *Namespace) Group(key any, items any) (any, error) {
if key == nil {
return nil, errors.New("nil is not a valid key to group by")
}
if g, ok := items.(collections.Grouper); ok {
return g.Group(key, items)
}
in := newSliceElement(items)
if g, ok := in.(collections.Grouper); ok {
return g.Group(key, items)
}
return nil, fmt.Errorf("grouping not supported for type %T %T", items, in)
}
// IsSet returns whether a given array, channel, slice, or map in c has the given key
// defined.
func (ns *Namespace) IsSet(c any, key any) (bool, error) {
av := reflect.ValueOf(c)
kv := reflect.ValueOf(key)
switch av.Kind() {
case reflect.Array, reflect.Chan, reflect.Slice:
k, err := cast.ToIntE(key)
if err != nil {
return false, fmt.Errorf("isset unable to use key of type %T as index", key)
}
if av.Len() > k {
return true, nil
}
case reflect.Map:View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Only call group on page collections: `{{ $g := group "featured" (where .Site.RegularPages "Params.featured" true) }}`.
- For arbitrary data, build groups manually with a dict: range the items and append each to `$groups` keyed by the field, e.g. via `merge`/`append` on a map of slices.
- For taxonomy-style grouping of pages by a field, use Hugo taxonomies or `.Pages.GroupByParam "field"` instead.
Example fix
<!-- before -->
{{ $g := group "type" .Site.Data.products.items }}
<!-- after -->
{{ $groups := dict }}
{{ range .Site.Data.products.items }}
{{ $k := .type }}
{{ $groups = merge $groups (dict $k (append . (index $groups $k | default slice))) }}
{{ end }} Defensive patterns
Strategy: type-guard
Validate before calling
{{/* GroupBy operates on Pages; confirm you have a Pages collection */}}
{{ with .Pages }}{{ $g := .GroupBy "Section" }}{{ end }} Type guard
{{ if eq (printf "%T" $coll) "page.Pages" }}{{ $g := $coll.GroupBy $field }}{{ end }} Prevention
- Call GroupBy/GroupByParam only on Pages collections, not on arbitrary slices or maps
- Ensure the field you group by is a supported type (string, int, time) on every page
- After `where`/`first` chains, verify the result is still a Pages collection before grouping
When it happens
Trigger: `{{ group "key" (slice "a" "b") }}`, `{{ group "x" .Params.items }}` (a []any from front matter), or grouping a map — anything that isn't a Pages collection.
Common situations: Attempting to use `group` as a generic group-by over data files or params (developers expect SQL-like GROUP BY), or passing `.Data.Terms`/site data instead of Pages. The doc comment states it's currently Pages-only.
Related errors
- arguments to symdiff must be slices or arrays
- can't iterate over %T
- invalid dictionary key
- nil is not a valid key to group by
- symdiff: failed to convert value: %w
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/e43959e22586e983.json.
Report an issue: GitHub ↗.