{"record":{"id":"e4f2a223d729128e","repo":"jaegertracing/jaeger","slug":"root-span-top-hit-missing-source","errorCode":null,"errorMessage":"root span top-hit missing _source","messagePattern":"root span top-hit missing _source","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/v2/elasticsearch/tracestore/core/summary.go","lineNumber":261,"sourceCode":"\n// parseRootSpan returns the service and operation of the trace's root span, taken\n// from the earliest span that has no parentSpanID (see buildTraceSummariesAggregation).\n//\n// Empty values with a nil error are returned when the trace has no parentless span\n// (a valid outcome); a malformed top-hit _source is surfaced as an error rather\n// than dropped.\nfunc parseRootSpan(bucket esclient.AggregationBucket) (serviceName, operationName string, err error) {\n\trootSpan, ok := bucket.Filter(\"root_span\")\n\tif !ok {\n\t\treturn \"\", \"\", nil\n\t}\n\ttopHits, ok := rootSpan.TopHits(\"root_hit\")\n\tif !ok || len(topHits.Hits) == 0 {\n\t\treturn \"\", \"\", nil\n\t}\n\tsource := topHits.Hits[0].Source\n\tif len(source) == 0 {\n\t\treturn \"\", \"\", errors.New(\"root span top-hit missing _source\")\n\t}\n\tvar parsed rootSpanSource\n\tif err := json.Unmarshal(source, &parsed); err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to decode root span source: %w\", err)\n\t}\n\treturn parsed.Process.ServiceName, parsed.OperationName, nil\n}\n","sourceCodeStart":243,"sourceCodeEnd":269,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/elasticsearch/tracestore/core/summary.go#L243-L269","documentation":"This error is raised by parseRootSpan in summary.go when the top-hit document of the root-span aggregation (named \"root_hit\") has an empty _source field. Trace summaries need the root span's service name and operation name, which are read from the hit's _source; without it, parsing cannot proceed and parseTraceSummaries surfaces the error.","triggerScenarios":"Calling the trace summary read path where the ES top-hits aggregation returns a hit whose Source bytes are empty — e.g. stored_span documents written without full _source, mapping-only hits, or fetch_source disabled in the search request.","commonSituations":"Indices written by an older/different writer that did not store full documents; custom index templates with source filtering; querying a summary endpoint against indices lacking the expected root-span documents.","solutions":["Verify the span documents in Elasticsearch actually contain full _source (check a raw document with GET <index>/_doc/<id>).","Ensure the search request does not disable or filter out _source for the root_hit top-hits aggregation.","Re-index or rewrite affected indices if documents were written without source by an older writer.","Check index templates/mappings for source filtering that empties _source."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-flight: confirm a sample root-span document has non-empty _source\nvar doc map[string]any\nerr := esAPI.Get(ctx, index, id, &doc)\nif err != nil || len(doc) == 0 { /* index lacks source data */ }","typeGuard":null,"tryCatchPattern":"summary, err := reader.GetTraceSummary(ctx, traceID)\nif err != nil && strings.Contains(err.Error(), \"root span top-hit missing _source\") {\n    // fall back to full trace fetch or reindex the affected index\n}","preventionTips":["Ensure span writers store full documents (do not disable _source).","Check index templates for source filtering that would empty _source.","After writer upgrades, re-index older indices written without full source."],"tags":["elasticsearch","top-hits","response-parsing"],"backgroundTag":"empty-source-in-hit","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}