{"record":{"id":"2581a67b622b8cb1","repo":"jaegertracing/jaeger","slug":"nil-search-response","errorCode":null,"errorMessage":"nil search response","messagePattern":"nil search response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/v2/elasticsearch/tracestore/core/service_operation.go","lineNumber":181,"sourceCode":"\tresp, err := s.searcher.Search(ctx, indices, esclient.SearchRequest{\n\t\tSize:  0,\n\t\tQuery: query.NewTermQuery(serviceName, service),\n\t\tAggregations: map[string]query.Aggregation{\n\t\t\toperationsAggregation: query.NewTermsAggregation(operationNameField).Size(maxDocCount),\n\t\t},\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"search operations failed: %w\", err)\n\t}\n\treturn aggregationKeys(resp, operationsAggregation)\n}\n\n// aggregationKeys extracts the bucket keys of a named terms aggregation. A\n// response with no aggregations yields an empty slice; a response missing the\n// requested aggregation is an error.\nfunc aggregationKeys(resp *esclient.SearchResponse, name string) ([]string, error) {\n\tif resp == nil {\n\t\treturn nil, errors.New(\"nil search response\")\n\t}\n\tif resp.Aggregations == nil {\n\t\treturn []string{}, nil\n\t}\n\tagg, ok := resp.Aggregations.Terms(name)\n\tif !ok {\n\t\treturn nil, errors.New(\"could not find aggregation of \" + name)\n\t}\n\tkeys := make([]string, 0, len(agg.Buckets))\n\tfor _, bucket := range agg.Buckets {\n\t\tkeys = append(keys, bucket.Key)\n\t}\n\treturn keys, nil\n}\n\nfunc hashCode(s dbmodel.Service) string {\n\th := fnv.New64a()\n\th.Write([]byte(s.ServiceName))","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/elasticsearch/tracestore/core/service_operation.go#L163-L199","documentation":"This error is raised by aggregationKeys in service_operation.go when the Elasticsearch SearchResponse pointer itself is nil. A nil response cannot carry any aggregation data, so the function fails fast; in contrast, a non-nil response with no Aggregations section yields an empty slice rather than an error.","triggerScenarios":"getServices or getOperations receiving a nil *SearchResponse from the searcher — typically when the underlying ES client transport fails in a way that yields a nil response alongside an error, or a test/mock returning (nil, nil).","commonSituations":"Custom or mocked searcher implementations returning nil responses without errors; lower-level client bugs or unexpected transport conditions; incorrect error handling upstream that lets a nil response propagate.","solutions":["Ensure the searcher/client always returns either a valid response or a non-nil error, and check errors before using the response.","Fix mock implementations used in tests to return a non-nil SearchResponse or an error.","If a nil response with nil error is reproducible, report/investigate the underlying client call for transport failures."],"exampleFix":"// before\nresp, err := searcher.Search(ctx, req)\nkeys, err := aggregationKeys(resp, aggName) // panics/nils if resp==nil and err==nil\n// after\nresp, err := searcher.Search(ctx, req)\nif err != nil || resp == nil { return err }\nkeys, err := aggregationKeys(resp, aggName)","handlingStrategy":"type-guard","validationCode":"if resp == nil {\n    return fmt.Errorf(\"searcher returned nil response\")\n}","typeGuard":"func validResponse(r *esclient.SearchResponse) bool { return r != nil }","tryCatchPattern":"keys, err := aggregationKeys(resp, name)\nif err != nil && err.Error() == \"nil search response\" {\n    // treat as upstream client/transport failure; retry or surface 502\n}","preventionTips":["Always check the searcher's error before touching the response pointer.","Make mocks/tests return either (response, nil) or (nil, err), never (nil, nil).","Wrap client calls so a nil response with nil error is impossible."],"tags":["elasticsearch","nil-response","response-parsing"],"backgroundTag":"nil-response-received","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}