apache/druid · error · ISE

Cannot have a null result!

Error message

Cannot have a null result!

What it means

FinalizeResultsQueryRunner post-processes query results, and for by-segment results it casts each input to a Result<BySegmentResultValueClass<T>>. The null check (an internal invariant) throws IllegalStateException when a null result reaches the finalize function — the value arrived as null even though the cast line executes first, so this check exists to fail loudly on a null that violates the runner's contract.

Solutions

  1. Find the upstream QueryRunner returning null results and make it return an empty Result or skip emission instead.
  2. Wrap custom runners so null results are filtered out before the finalize stage.
  3. Verify caching/merge configuration (by-segment query caching) isn't producing null entries in the results list.

Example fix

// before
return results.isEmpty() ? null : new Result<>(...); // null leaks to finalize
// after
return new Result<>(timestamp, new BySegmentResultValueClass<>(results, segmentId, interval)); // always non-null
Defensive patterns

Strategy: try-catch

Validate before calling

if (input == null) {
  // skip or substitute an empty result before feeding the finalize chain
}

Try / catch

try {
  Result<BySegmentResultValueClass<T>> r = finalize(input);
} catch (IllegalStateException e) {
  if (e.getMessage().contains("Cannot have a null result")) {
    // log and skip this result
  } else { throw e; }
}

Prevention

When it happens

Trigger: A query tool/wrapper or custom QueryRunner upstream yields a null Result into the finalize chain when merging by-segment results (e.g. during caching or concatenation merges).

Common situations: Custom QueryRunner implementations or extensions that return null instead of an empty/absent result; query lifecycle bugs where a segment result was dropped but the pipeline still expected a Result object.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/07f79a9a762ea5c9. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/FinalizeResultsQueryRunner.java:92

      metricManipulationFn = MetricManipulatorFns.identity();
    }

    if (isBySegment) {
      finalizerFn = new Function<T, Result<BySegmentResultValue<T>>>()
      {
        final Function<T, T> baseFinalizer = toolChest.makePostComputeManipulatorFn(
            query,
            metricManipulationFn
        );

        @Override
        public Result<BySegmentResultValue<T>> apply(T input)
        {
          //noinspection unchecked (input is not actually a T; see class-level javadoc)
          Result<BySegmentResultValueClass<T>> result = (Result<BySegmentResultValueClass<T>>) input;

          if (input == null) {
            throw new ISE("Cannot have a null result!");
          }

          BySegmentResultValue<T> resultsClass = result.getValue();

          final List<T> originalResults = resultsClass.getResults();
          final ArrayList<T> transformedResults = new ArrayList<>(originalResults.size());
          for (T originalResult : originalResults) {
            transformedResults.add(baseFinalizer.apply(originalResult));
          }

          return new Result<>(
              result.getTimestamp(),
              new BySegmentResultValueClass<>(
                  transformedResults,
                  resultsClass.getSegmentId(),
                  resultsClass.getInterval()
              )
          );

View on GitHub (pinned to 9b90983fd2)