apache/druid · error · AggregatorFactoryNotMergeableException

AggregatorFactoryNotMergeableException

Error message

AggregatorFactoryNotMergeableException

What it means

SimpleDoubleAggregatorFactory.getMergingFactory throws AggregatorFactoryNotMergeableException when another aggregator factory does not have the same name and the same class. Druid needs to combine partial aggregation results from multiple shards/segments, and this only works when both factories represent the same double aggregation over the same output name. The exception signals the query planner asked to merge two incompatible aggregations.

Source

Thrown at processing/src/main/java/org/apache/druid/query/aggregation/SimpleDoubleAggregatorFactory.java:196

  {
    return object;
  }

  @Override
  public List<String> requiredFields()
  {
    return fieldName != null
           ? Collections.singletonList(fieldName)
           : fieldExpression.get().analyzeInputs().getRequiredBindingsList();
  }

  @Override
  public AggregatorFactory getMergingFactory(AggregatorFactory other) throws AggregatorFactoryNotMergeableException
  {
    if (other.getName().equals(this.getName()) && this.getClass() == other.getClass()) {
      return getCombiningFactory();
    } else {
      throw new AggregatorFactoryNotMergeableException(this, other);
    }
  }

  @Override
  public int hashCode()
  {
    return Objects.hash(fieldName, expression, name);
  }

  @Override
  public boolean equals(Object o)
  {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure both aggregation sides use the same output name for the double aggregator
  2. Ensure both sides use the same aggregator type (doubleSum/doubleMin/doubleMax/doubleFirst etc.) so classes match
  3. Rewrite the query so subquery and outer aggregations are consistent, or remove the merging requirement by pushing aggregations into the inner query
  4. If data was ingested with an older schema, re-ingest or use a query that avoids cross-shard merge of mismatched factories

Example fix

// before
 Aggregations: aggColumnAggregate: { type: "doubleSum", name: "sum_x" } and { type: "longSum", name: "sum_x" }
// after
 Use consistent factories:
 { type: "doubleSum", name: "sum_x" } on both subquery and outer query
Defensive patterns

Strategy: validation

Validate before calling

boolean mergeable(AggregatorFactory a, AggregatorFactory b) {
  return a.getName().equals(b.getName()) && a.getClass() == b.getClass();
}

Type guard

boolean isMergeableDoublePair(AggregatorFactory other, SimpleDoubleAggregatorFactory self) {
  return other instanceof SimpleDoubleAggregatorFactory && other.getName().equals(self.getName());
}

Try / catch

try {
  AggregatorFactory merged = factory.getMergingFactory(other);
} catch (AggregatorFactoryNotMergeableException e) {
  LOGGER.warn(e, "Skipping merge for incompatible aggregator factories: %s vs %s", e.getFactory1(), e.getFactory2());
}

Prevention

When it happens

Trigger: Distributing a query across segments where one shard's aggregator factory for a given name is a SimpleDoubleAggregatorFactory but the other shard yields a different class (or a different output name), causing DruidAggregationQueryTool/merge logic to call getMergingFactory with a mismatched other.

Common situations: Queries mixing subqueries or datasources where one side has a double aggregator named x and the other has a differently-named or differently-typed aggregator; post-inception changes where subquery pushdown rewrites aggregations and names diverge between layers.

Related errors


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