gohugoio/hugo · error
invalid type %T in related search
Error message
invalid type %T in related search
What it means
All related-content searches funnel through Pages.withInvertedIndex, which type-asserts the first page in the collection to RelatedDocsHandlerProvider to obtain the site's related-docs cache and inverted index. If that assertion fails — the collection's elements aren't real page objects backed by the site — the search cannot proceed and this error names the actual type found.
Source
Thrown at resources/page/pages_related.go:129
}
return p.search(ctx, opts)
}
func (p Pages) search(ctx context.Context, opts related.SearchOpts) (Pages, error) {
return p.withInvertedIndex(ctx, func(idx *related.InvertedIndex) ([]related.Document, error) {
return idx.Search(ctx, opts)
})
}
func (p Pages) withInvertedIndex(ctx context.Context, search func(idx *related.InvertedIndex) ([]related.Document, error)) (Pages, error) {
if len(p) == 0 {
return nil, nil
}
d, ok := p[0].(RelatedDocsHandlerProvider)
if !ok {
return nil, fmt.Errorf("invalid type %T in related search", p[0])
}
cache := d.GetInternalRelatedDocsHandler()
searchIndex, err := cache.getOrCreateIndex(ctx, p)
if err != nil {
return nil, err
}
result, err := search(searchIndex)
if err != nil {
return nil, err
}
if len(result) > 0 {
mp := make(Pages, len(result))
for i, match := range result {
mp[i] = match.(Page)View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Run Related on a real page collection such as `site.RegularPages` or `.Pages` instead of a hand-assembled slice.
- If you filtered/assembled the collection yourself, make sure every element originates from site pages (e.g. use `where` on site.Pages rather than building a new slice from arbitrary values).
- In custom Go code or tests, use pages created by the Hugo site (hugolib.Test) so they implement the internal RelatedDocsHandlerProvider interface.
Example fix
<!-- before: hand-built collection of non-page values -->
{{ $coll := slice .Title .Section }}
{{ $related := $coll.Related . }}
<!-- after: search a real page collection -->
{{ $related := site.RegularPages.Related . }} Defensive patterns
Strategy: type-guard
Type guard
func validRelatedKeyVal(v any) bool {
switch v.(type) {
case string, []string, time.Time:
return true
default:
return false
}
} Prevention
- In related searches, index values must be strings, string slices, or dates — convert numbers with `string`/`printf` first
- Ensure front matter fields used as related indices have consistent types across all pages
- Declare related indices explicitly in site config so indexed params are known types
- Add a test site build covering pages with edge-case front matter types
When it happens
Trigger: Calling `.Related`, `.RelatedIndices`, or `.RelatedTo` on a Pages collection whose first element is not a full site-backed Page — e.g. a collection hand-built in a template from non-page values, or synthetic/wrapped page types (custom code, tests) that don't implement RelatedDocsHandlerProvider.
Common situations: Building a slice with `slice`/`append` in templates that mixes pages with other values, template constructs that yield page-like adapters rather than concrete pages, or (for Hugo module/tool developers) passing mock pages into the related API.
Related errors
- %T can not be transformed
- %T cannot be merged by language
- invalid argument type %T
- error building site: %w
- failed to decode related config: %w
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/5371f4c10f41a2a1.json.
Report an issue: GitHub ↗.