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

  1. 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.
  2. Use the Hugo group function (e.g. .Pages.GroupBy) which returns properly typed PagesGroup, instead of manually constructing the slice.
  3. 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

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


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)