gohugoio/hugo · error
index %q not found
Error message
index %q not found
What it means
`InvertedIndex.Search` (related/inverted_index.go:346) restricts a related-content query to the index names given in SearchOpts.Indices or in named argument slices. Each name is looked up against the configured `related.indices` (config lookup at getIndexCfg); an unknown name means the query references an index that was never configured, so Hugo fails instead of silently returning no matches.
Source
Thrown at related/inverted_index.go:359
// against query options in opts.
// The resulting document set will be sorted according to number of matches
// and the index weights, and any matches with a rank below the configured
// threshold (normalize to 0..100) will be removed.
// If an index name is provided, only that index will be queried.
func (idx *InvertedIndex) Search(ctx context.Context, opts SearchOpts) ([]Document, error) {
var (
queryElements []queryElement
configs IndicesConfig
)
if len(opts.Indices) == 0 {
configs = idx.cfg.Indices
} else {
configs = make(IndicesConfig, len(opts.Indices))
for i, indexName := range opts.Indices {
cfg, found := idx.getIndexCfg(indexName)
if !found {
return nil, fmt.Errorf("index %q not found", indexName)
}
configs[i] = cfg
}
}
for _, cfg := range configs {
var keywords []Keyword
if opts.Document != nil {
k, err := opts.Document.RelatedKeywords(cfg)
if err != nil {
return nil, err
}
keywords = append(keywords, k...)
}
if cfg.Type == TypeFragments {
for _, fragment := range opts.Fragments {
keywords = append(keywords, FragmentKeyword(fragment))
}View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Add the missing index to `related.indices` in your site config (e.g. `[[related.indices]] name = 'tags' weight = 80`).
- Fix the index name in the template call to match a configured index (names are lower-case).
- If you customized `related`, remember it replaces the defaults entirely — re-declare any default indices you still query.
Example fix
// before (layouts template)
{{ $related := site.RegularPages.Related (dict "document" . "indices" (slice "tags")) }}
# after (hugo.toml)
[related]
[[related.indices]]
name = "tags"
weight = 80 Defensive patterns
Strategy: validation
Validate before calling
# Declare every index you query in site config before using .Related
[related]
[[related.indices]]
name = "keywords"
weight = 100 Type guard
func hasIndex(cfg related.Config, name string) bool {
for _, ic := range cfg.Indices {
if strings.EqualFold(ic.Name, name) { return true }
}
return false
} Try / catch
related, err := idx.Search(cfg)
if err != nil {
return fmt.Errorf("related search failed — is the index declared in [related.indices]?: %w", err)
} Prevention
- Only pass index names to related-content searches that appear under `related.indices` in site config
- Remember Hugo's defaults are `keywords` and `date` — any other name must be configured explicitly
- Keep template `.RelatedIndices` arguments in sync when renaming indices in config
When it happens
Trigger: Calling `.Related` / `site.RegularPages.Related` with an `indices` option or a named argument (e.g. `keyvals "series" ...`) whose name doesn't match any entry in the site's `related.indices` config (inverted_index.go:357-359 and 395-398).
Common situations: Template uses `related.indices` names that were removed or renamed in config; relying on Hugo's default related config (keywords, date) while querying a custom index like `tags` that was never added; case/typo mismatches (index names are lower-cased in config decoding).
Related errors
- failed to decode related config: %w
- config needs a filename
- invalid argument type %T
- invalid type %T in related search
- startLevel: %w
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/887b849d275104e1.json.
Report an issue: GitHub ↗.