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

  1. Add the missing index to `related.indices` in your site config (e.g. `[[related.indices]] name = 'tags' weight = 80`).
  2. Fix the index name in the template call to match a configured index (names are lower-case).
  3. 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

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


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/887b849d275104e1.json. Report an issue: GitHub ↗.