apache/druid · error · UnsupportedOperationException

[%s] does not implement makeAggregateCombiner()

Error message

[%s] does not implement makeAggregateCombiner()

What it means

AggregatorFactory.makeAggregateCombiner() is an abstract-style hook that must return an AggregateCombiner used when merging pre-aggregated segments (e.g. during IndexMerger merges). The base class throws this UOE to signal that the concrete aggregator factory does not support combining-based merging, so an attempt to merge segments containing this aggregator cannot proceed.

Source

Thrown at processing/src/main/java/org/apache/druid/query/aggregation/AggregatorFactory.java:130

   * @param rhs The right hand side of the combine
   *
   * @return an object representing the combination of lhs and rhs, this can be a new object or a mutation of the inputs
   */
  @Nullable
  public abstract Object combine(@Nullable Object lhs, @Nullable Object rhs);

  /**
   * Creates an AggregateCombiner to fold rollup aggregation results from serveral "rows" of different indexes during
   * index merging. AggregateCombiner implements the same logic as {@link #combine}, with the difference that it uses
   * {@link org.apache.druid.segment.ColumnValueSelector} and it's subinterfaces to get inputs and implements {@code
   * ColumnValueSelector} to provide output.
   *
   * @see AggregateCombiner
   * @see org.apache.druid.segment.IndexMerger
   */
  public AggregateCombiner makeAggregateCombiner()
  {
    throw new UOE("[%s] does not implement makeAggregateCombiner()", this.getClass().getName());
  }

  /**
   * Creates an {@link AggregateCombiner} which supports nullability.
   * Implementations of {@link AggregatorFactory} which need to Support Nullable Aggregations are encouraged
   * to extend {@link NullableNumericAggregatorFactory} instead of overriding this method.
   * Default implementation calls {@link #makeAggregateCombiner()} for backwards compatibility.
   *
   * @see AggregateCombiner
   * @see NullableNumericAggregatorFactory
   */
  public AggregateCombiner makeNullableAggregateCombiner()
  {
    return makeAggregateCombiner();
  }

  /**
   * Returns an AggregatorFactory that can be used to combine the output of aggregators from this factory. It is used

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Override makeAggregateCombiner() in your AggregatorFactory subclass to return a proper AggregateCombiner for your aggregator
  2. If supporting nullable aggregations, extend NullableNumericAggregatorFactory instead of implementing the method directly
  3. Use an aggregator type that supports combining (implements getCombiningFactory/makeAggregateCombiner) in merge scenarios

Example fix

// before
public class MyAggregatorFactory extends AggregatorFactory {
  // no makeAggregateCombiner override
}
// after
public class MyAggregatorFactory extends AggregatorFactory {
  @Override
  public AggregateCombiner makeAggregateCombiner() {
    return new MyAggregateCombiner();
  }
}
Defensive patterns

Strategy: type-guard

Validate before calling

// before merging
if (!(factory instanceof AggregatorFactory) || factory.getClass().equals(AggregatorFactory.class)) {
  throw new IllegalStateException("Aggregator must override makeAggregateCombiner()");
}

Type guard

boolean supportsCombining(AggregatorFactory f) {
  try { f.makeAggregateCombiner(); return true; } catch (UnsupportedOperationException e) { return false; }
}

Try / catch

try {
  combiner = factory.makeAggregateCombiner();
} catch (UnsupportedOperationException e) {
  log.error("Aggregator %s cannot merge segments", factory.getClass(), e);
  throw new QueryInterruptedException("aggregator-not-mergeable");
}

Prevention

When it happens

Trigger: Calling makeAggregateCombiner() (directly or via combiner()/makeNullableAggregateCombiner()) on an AggregatorFactory subclass that has not overridden the method, then using it in segment merging or nullable aggregation paths.

Common situations: Custom aggregator implementations missing the override; using an aggregator type in a rollup/merge context that only supports incremental aggregation; version changes where combining support became required for a code path.

Understand the failure class

Background: "NotImplementedError: Subclasses should override this method" / "must be implemented" — abstract method errors explained — this error's family across 40 libraries.

Related errors


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