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

  1. Only call group on page collections: `{{ $g := group "featured" (where .Site.RegularPages "Params.featured" true) }}`.
  2. 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.
  3. 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

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


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/e43959e22586e983.json. Report an issue: GitHub ↗.