gohugoio/hugo · error
type %T is not a PageGroup
Error message
type %T is not a PageGroup
What it means
Returned by PageGroup.Slice when converting a []any into a PagesGroup for the template `slice`/collections functions: every element must be a PageGroup, and one element is some other type. Hugo fails fast rather than silently dropping the mismatched element.
Source
Thrown at resources/page/pagegroup.go:393
if p.Key != otherP.Key {
return false
}
return p.Pages.ProbablyEq(otherP.Pages)
}
// Slice is for internal use.
// for the template functions. See collections.Slice.
func (p PageGroup) Slice(in any) (any, error) {
switch items := in.(type) {
case PageGroup:
return items, nil
case []any:
groups := make(PagesGroup, len(items))
for i, v := range items {
g, ok := v.(PageGroup)
if !ok {
return nil, fmt.Errorf("type %T is not a PageGroup", v)
}
groups[i] = g
}
return groups, nil
default:
return nil, fmt.Errorf("invalid slice type %T", items)
}
}
// Len returns the number of pages in the page group.
func (psg PagesGroup) Len() int {
l := 0
for _, pg := range psg {
l += len(pg.Pages)
}
return l
}
View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Ensure every element of the slice is a PageGroup — don't mix Pages, strings, or maps with grouped results
- Use the output of .GroupBy* directly instead of rebuilding it with slice/append
- If you need pages, use .Pages of each group rather than the groups themselves
Example fix
// before
{{ $mixed := slice (index $groups 0) .Site.RegularPages }}
// after
{{ $onlyGroups := slice (index $groups 0) (index $groups 1) }} Defensive patterns
Strategy: type-guard
Type guard
{{ $isPageGroup := and (reflect.IsMap . | not) (isset . "Key") (isset . "Pages") }} Prevention
- Only pass the result of .GroupBy/.GroupByDate/.GroupByParam (a PageGroups value) to functions expecting PageGroup
- Don't mix plain page slices and grouped results in the same template variable
- When paginating groups, pass the whole PageGroups result to .Paginate, not individual elements you constructed yourself
When it happens
Trigger: Template code building a slice that mixes PageGroup values with other types, e.g. `{{ $g := slice (index $groups 0) .Site.Params.foo }}` or appending a Page/string into a slice whose first element is a PageGroup, then passing it where a PagesGroup is expected.
Common situations: Custom templates combining results of .GroupBy/.GroupByDate with plain pages or strings, iterating grouped output and rebuilding slices incorrectly, or partials that receive heterogeneous data.
Related errors
- arguments to symdiff must be slices or arrays
- can't iterate over %T
- text must be a string
- first argument must be a map
- type %T not supported
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/34b2904ed9795158.json.
Report an issue: GitHub ↗.