apache/druid · error · UnsupportedOperationException

[ ] 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.

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.

Appendix: 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)