{"record":{"id":"04bbd04925d0d72f","repo":"hashicorp/consul","slug":"no-indexer-was-supplied-when-creating-a-new-cache","errorCode":null,"errorMessage":"no indexer was supplied when creating a new cache Index","messagePattern":"no indexer was supplied when creating a new cache Index","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/controller/cache/index/index.go","lineNumber":22,"sourceCode":"package index\n\nimport (\n\t\"github.com/hashicorp/consul/proto-public/pbresource\"\n\tiradix \"github.com/hashicorp/go-immutable-radix/v2\"\n)\n\ntype Index struct {\n\tname     string\n\trequired bool\n\tindexer  MultiIndexer\n}\n\nfunc New(name string, i Indexer, opts ...IndexOption) *Index {\n\tif name == \"\" {\n\t\tpanic(\"all indexers must have a non-empty name\")\n\t}\n\tif i == nil {\n\t\tpanic(\"no indexer was supplied when creating a new cache Index\")\n\t}\n\n\tvar multiIndexer MultiIndexer\n\tswitch v := i.(type) {\n\tcase SingleIndexer:\n\t\tmultiIndexer = singleIndexWrapper{indexer: v}\n\tcase MultiIndexer:\n\t\tmultiIndexer = v\n\tdefault:\n\t\tpanic(\"The Indexer must also implement one of the SingleIndexer or MultiIndexer interfaces\")\n\t}\n\n\tidx := &Index{\n\t\tname:    name,\n\t\tindexer: multiIndexer,\n\t}\n\n\tfor _, opt := range opts {","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/hashicorp/consul/blob/2397ff0d763d34f2fe37fe59fde6a7f7fc430a3e/internal/controller/cache/index/index.go#L4-L40","documentation":"index.New requires both a name and an actual Indexer implementation. Passing a nil Indexer panics at construction: a named index with nothing to compute it would silently produce empty query results, so the constructor fails fast. Note the check only catches an untyped nil interface — a typed nil pointer stored in the interface passes here and typically blows up later in the type switch or at query time.","triggerScenarios":"Calling index.New(\"name\", nil), or passing an indexer variable that was declared but never assigned, or one returned as nil by a constructor function that swallowed an error.","commonSituations":"Index construction refactored into helper functions that can return nil; building indexes conditionally where some branch forgets to assign; partially completed migrations to the controller framework.","solutions":["Construct and pass a real indexer implementation (SingleIndexer or MultiIndexer)","If a helper may produce nil, check before calling New: if idxr == nil { return errors.New(\"indexer required\") }","Construct indexes unconditionally at controller setup rather than leaving a declared-but-nil variable"],"exampleFix":"// before\nvar indexer index.SingleIndexer\n// ... branch forgot to assign indexer\nidx := index.New(\"kind\", indexer) // panic: no indexer was supplied\n\n// after\nidx := index.New(\"kind\", index.SingleIndexer(...))","handlingStrategy":"validation","validationCode":"// check the interface variable before constructing the Index\nfunc buildIndex(name string, idxr index.Indexer) (*index.Index, error) {\n    if idxr == nil {\n        return nil, fmt.Errorf(\"index %q: indexer must not be nil\", name)\n    }\n    return index.New(name, idxr), nil\n}","typeGuard":"// catches typed-nil pointers stored in the interface too\nfunc isNilIndexer(i index.Indexer) bool {\n    if i == nil {\n        return true\n    }\n    v := reflect.ValueOf(i)\n    return v.Kind() == reflect.Ptr && v.IsNil()\n}","tryCatchPattern":null,"preventionTips":["Never let indexer constructors return (nil, nil); always propagate an error","Construct indexers inline in the index.New call where practical","Run controller setup in a unit test so nil wiring fails in CI, not in production"],"tags":["go","consul","controller","cache","panic","programmer-error","nil-safety"],"backgroundTag":null,"analyzedSha":"2397ff0d763d34f2fe37fe59fde6a7f7fc430a3e","analyzedAt":"2026-08-15T19:19:47.700Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}