gohugoio/hugo · error
index %q not valid
Error message
index %q not valid
What it means
When a related-content query is made with named key/value slices (the `keyvals`-style arguments), each slice's key must stringify to a non-empty index name via KeyString(). An empty result means the key wasn't a usable string, so Hugo rejects the query rather than searching an unnamed index (related/inverted_index.go:389-394).
Source
Thrown at related/inverted_index.go:393
for _, fragment := range opts.Fragments {
keywords = append(keywords, FragmentKeyword(fragment))
}
if opts.Document != nil {
if fp, ok := opts.Document.(FragmentProvider); ok {
for _, fragment := range fp.Fragments(ctx).Identifiers {
keywords = append(keywords, FragmentKeyword(fragment))
}
}
}
}
queryElements = append(queryElements, newQueryElement(cfg.Name, keywords...))
}
for _, slice := range opts.NamedSlices {
var keywords []Keyword
key := slice.KeyString()
if key == "" {
return nil, fmt.Errorf("index %q not valid", slice.Key)
}
conf, found := idx.getIndexCfg(key)
if !found {
return nil, fmt.Errorf("index %q not found", key)
}
for _, val := range slice.Values {
k, err := conf.ToKeywords(val)
if err != nil {
return nil, err
}
keywords = append(keywords, k...)
}
queryElements = append(queryElements, newQueryElement(conf.Name, keywords...))
}
if opts.Document != nil {
return idx.searchDate(ctx, opts.Document, opts.Document.PublishDate(), queryElements...)View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Ensure the first argument to `keyVals` in the template is a non-empty string naming a configured related index.
- Guard the template: skip the Related call when the variable holding the index name is empty (`{{ with $name }}...{{ end }}`).
Example fix
// before
{{ $related := site.RegularPages.Related (dict "document" . "namedSlices" (slice (keyVals $name "a"))) }}
// after
{{ with $name }}{{ $related := site.RegularPages.Related (dict "document" $ "namedSlices" (slice (keyVals . "a"))) }}{{ end }} Defensive patterns
Strategy: validation
Validate before calling
# An index used for search must be enabled and applicable [[related.indices]] name = "tags" weight = 80 # ensure weight > 0; weight 0 disables the index
Type guard
func indexUsable(ic related.IndexConfig) bool {
return ic.Weight > 0
} Try / catch
docs, err := idx.SearchDoc(doc, indices...)
if err != nil {
// "index not valid" => index exists but is disabled/unusable for this query
return fmt.Errorf("related index misconfigured: %w", err)
} Prevention
- Don't query indices whose weight is 0 (disabled)
- Match the query type to the index type (e.g. don't do fragment/text queries against a basic keyword index)
- After editing [related] config, exercise a page with `.Related` in a test build to catch invalid-index errors early
When it happens
Trigger: Passing a NamedSlice whose Key is not a string (or stringifies to "") to InvertedIndex.Search — in templates, calling `.Related` with a `keyvals` entry built from `keyVals` where the key argument is empty or a non-string value.
Common situations: Template code computing the index name from a variable that is empty for some pages (`keyVals $missingParam ...`), or passing a non-string object as the key in `keyVals`.
Related errors
- errKeyIsEmptyString
- %q is not a valid duration unit
- errMustTwoNumbersError
- strings: negative Repeat count
- error correction level must be one of low, medium, quartile,
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/f624fedc422a1b01.json.
Report an issue: GitHub ↗.