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 iterating a []any slice and encountering an element that is not of type PageGroup. The %T verb substitutes the actual Go type of the offending element. This is an internal method used by template functions to construct a PagesGroup from heterogeneous input.
Solutions
- Ensure every element in the []any slice passed to PageGroup.Slice is actually a PageGroup value — the error message names the offending type via %T.
- Use the Hugo group function (e.g. .Pages.GroupBy) which returns properly typed PagesGroup, instead of manually constructing the slice.
- Add a Go type assertion before calling Slice if you are building the slice programmatically.
Example fix
// before — mixed types in the slice
groups := []any{pg1, somePage, pg2}
result, err := pageGroup.Slice(groups)
// error: type page.Page is not a PageGroup
// after — all elements are PageGroup
result, err := pageGroup.Slice([]any{pg1, pg2})
// or use the template-level GroupBy which returns PagesGroup directly:
{{ range .Pages.GroupBy "Section" }}
{{ .Key }}: {{ .Pages }}
{{ end }} Defensive patterns
Strategy: type-guard
Type guard
// Type guard for PageGroup elements before calling Slice
func isPageGroup(v any) bool {
_, ok := v.(PageGroup)
return ok
}
// Filter a heterogeneous slice to only PageGroup values
func filterPageGroups(items []any) []PageGroup {
var groups []PageGroup
for _, v := range items {
if pg, ok := v.(PageGroup); ok {
groups = append(groups, pg)
}
}
return groups
} Try / catch
// Guard the Slice call with a pre-check
var valid []any
for _, v := range items {
if _, ok := v.(PageGroup); !ok {
return nil, fmt.Errorf("element of type %T is not a PageGroup", v)
}
valid = append(valid, v)
}
return pageGroup.Slice(valid) Prevention
- Prefer Hugo's built-in GroupBy template methods which return properly typed PagesGroup.
- Type-assert every element before building a []any for PageGroup.Slice.
- Avoid mixing Pages and PagesGroup in the same data pipeline — they are different types.
When it happens
Trigger: Calling .Slice on a PageGroup or passing a []any containing mixed types (some PageGroup, some not) to a template function that expects a PagesGroup. This typically happens in Go code or advanced templates that manually assemble page groups.
Common situations: A custom template or Go integration that builds a slice of mixed page groups and plain pages; accidentally passing Pages instead of PagesGroup to a grouping function; a template partial that receives unexpected types from a poorly typed data pipeline.
Related errors
- cannot convert type %T to Pages
- %T cannot be merged by language
- argument must be a slice
- assemble
- called apply using as type
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/34b2904ed9795158.
Report an issue: GitHub.
Appendix: 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 52c9bd7908)