{"record":{"id":"b2ccad1cc54fc52c","repo":"gohugoio/hugo","slug":"index-for-q-not-found","errorCode":null,"errorMessage":"index for %q not found","messagePattern":"index for %q not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"related/inverted_index.go","lineNumber":474,"sourceCode":"func (idx *InvertedIndex) search(ctx context.Context, query ...queryElement) ([]Document, error) {\n\treturn idx.searchDate(ctx, nil, zeroDate, query...)\n}\n\nfunc (idx *InvertedIndex) searchDate(ctx context.Context, self Document, upperDate time.Time, query ...queryElement) ([]Document, error) {\n\tmatchm := make(map[Document]*rank, 200)\n\tdefer func() {\n\t\tfor _, r := range matchm {\n\t\t\tputRank(r)\n\t\t}\n\t}()\n\n\tapplyDateFilter := !idx.cfg.IncludeNewer && !upperDate.IsZero()\n\tvar fragmentsFilter collections.SortedStringSlice\n\n\tfor _, el := range query {\n\t\tsetm, found := idx.index[el.Index]\n\t\tif !found {\n\t\t\treturn []Document{}, fmt.Errorf(\"index for %q not found\", el.Index)\n\t\t}\n\n\t\tconfig, found := idx.getIndexCfg(el.Index)\n\t\tif !found {\n\t\t\treturn []Document{}, fmt.Errorf(\"index config for %q not found\", el.Index)\n\t\t}\n\n\t\tfor _, kw := range el.Keywords {\n\t\t\tif docs, found := setm[kw]; found {\n\t\t\t\tfor _, doc := range docs {\n\t\t\t\t\tif compare.Eq(doc, self) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tif applyDateFilter {\n\t\t\t\t\t\t// Exclude newer than the limit given\n\t\t\t\t\t\tif doc.PublishDate().After(upperDate) {\n\t\t\t\t\t\t\tcontinue","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/related/inverted_index.go#L456-L492","documentation":"Returned by InvertedIndex.searchDate when the internal index map (idx.index) does not contain an entry for a query element's Index name. This is a lower-level lookup distinct from the config lookup: it checks the actual posting-list map. A mismatch implies the query element references an index that was never allocated during NewInvertedIndex.","triggerScenarios":"Reached only if a queryElement reaches searchDate with an Index name absent from idx.index. In normal flow Search validates names first (errors 523/525), so this is a defensive guard for internal callers that construct queryElements directly or a config/index-map inconsistency.","commonSituations":"Internal code constructing queryElement with an index name not passed to NewInvertedIndex; a config that was decoded after index construction so the map and config diverge; custom code that bypasses the Search entry validation.","solutions":["Ensure NewInvertedIndex is constructed with the same Config whose index names are used in queries.","Do not construct queryElement directly outside the package; use Search/SearchOpts which validates names.","Recreate the InvertedIndex if the related config changes at runtime."],"exampleFix":"// before: index built with one config, queried with names from another\nidx := related.NewInvertedIndex(cfgA)\nidx.searchDate(ctx, doc, t, queryElement{Index: \"onlyInCfgB\"})\n\n// after: rebuild with the active config\nidx := related.NewInvertedIndex(activeCfg)","handlingStrategy":"validation","validationCode":"// Ensure the index name was registered at construction.\nfunc registeredNames(idx *related.InvertedIndex) []string {\n    // idx.index keys are the allocated names; expose them in your wrapper\n    return /* names from the Config used to build idx */\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always go through Search/SearchOpts rather than constructing queryElement directly.","Pass the same Config to NewInvertedIndex that you later query against.","Recreate the InvertedIndex whenever related config changes."],"tags":["related","search","internal","index-map"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}