{"record":{"id":"87d52ae062b541fb","repo":"apache/druid","slug":"got-a-null-result-segments-are-missing","errorCode":null,"errorMessage":"Got a null result! Segments are missing!","messagePattern":"Got a null result! Segments are missing!","errorType":"exception","errorClass":"ISE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/ChainedExecutionQueryRunner.java","lineNumber":115,"sourceCode":"                    Iterables.transform(\n                        queryables,\n                        input -> {\n                          if (input == null) {\n                            throw new ISE(\"Null queryRunner! Looks to be some segment unmapping action happening\");\n                          }\n\n                          final AbstractPrioritizedQueryRunnerCallable<Iterable<T>, T> callable = new AbstractPrioritizedQueryRunnerCallable<>(\n                              priority,\n                              input\n                          )\n                          {\n                            @Override\n                            public Iterable<T> call()\n                            {\n                              try {\n                                Sequence<T> result = input.run(threadSafeQueryPlus, responseContext);\n                                if (result == null) {\n                                  throw new ISE(\"Got a null result! Segments are missing!\");\n                                }\n\n                                List<T> retVal = result.toList();\n                                if (retVal == null) {\n                                  throw new ISE(\"Got a null list of results\");\n                                }\n\n                                return retVal;\n                              }\n                              catch (QueryInterruptedException e) {\n                                throw new RuntimeException(e);\n                              }\n                              catch (QueryTimeoutException e) {\n                                throw e;\n                              }\n                              catch (Exception e) {\n                                if (query.context().isDebug()) {\n                                  log.error(e, \"Exception with one of the sequences!\");","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/ChainedExecutionQueryRunner.java#L97-L133","documentation":"Thrown by ChainedExecutionQueryRunner's per-segment runnable when a query runner's run() method returns a null Sequence. In Druid, every executed query must produce a non-null result sequence; null indicates the segment backing the runner is gone or the runner is broken. The library throws ISE to fail fast rather than propagate a NullPointerException later.","triggerScenarios":"A QueryRunner returned by the segment/loading walker returns null from run(), typically because the segment referenced by the query is no longer loaded, the timeline returned no segment but a runner was still registered, or a custom/extension QueryRunner violates the contract of returning a Sequence.","commonSituations":"Segments dropped by a kill task or retention policy while a query is in flight; historical node serving a segment that was removed from its segment cache; custom QueryRunner implementations (extensions, test stubs) that return null instead of Sequences.empty(); mismatched segment load/serve configuration after restarts.","solutions":["Check the historical node logs for segment load/drop events around the query time; re-fetch segment metadata from the coordinator","Verify the segment is present on the node serving the query (segment cache dir, druid.segment-cache settings) and force re-download if missing","Retry the query; if transient (segment swap during query), ensure query retry is enabled on the broker","If a custom QueryRunner is in the stack, fix it to return Sequences.empty() or a valid Sequence instead of null"],"exampleFix":"// before\npublic Sequence<T> run(QueryPlus<T> query, Map<String, Object> context) {\n  if (segmentMissing) {\n    return null;\n  }\n  ...\n}\n// after\npublic Sequence<T> run(QueryPlus<T> query, Map<String, Object> context) {\n  if (segmentMissing) {\n    return Sequences.empty();\n  }\n  ...\n}","handlingStrategy":"try-catch","validationCode":"// before issuing query, verify segments served for the datasource/interval\nSegmentMetadataQuery meta = new SegmentMetadataQuery(\n    new TableDataSource(\"myDs\"), Granularities.ALL, null, null, null);\n// empty/missing segment metadata signals the segment may be absent\n","typeGuard":"boolean hasValidResult(Sequence<?> seq) {\n  return seq != null;\n}","tryCatchPattern":"try {\n  Sequence<T> seq = runner.run(queryPlus, context);\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"null result\")) {\n    // treat as segment-missing: refresh segments and retry\n  }\n}","preventionTips":["Ensure custom QueryRunners never return null; return Sequences.empty()","Keep segment load/drop metadata in sync with the coordinator before serving queries","Retry transient segment-missing failures at the broker level"],"tags":["druid","query-execution","segment-missing","null-result"],"backgroundTag":"internal-invariant-violation","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}