apache/druid · error · AggregatorFactoryNotMergeableException

can't merge [%s : %s] and [%s : %s] , with detailed info [%s

Error message

can't merge [%s : %s] and [%s : %s] , with detailed info [%s] and [%s]

What it means

getMergingFactory() merges two AggregatorFactory instances only when they have the same output name and equal combining factories. If the names differ or the combining factories are not equal, it throws AggregatorFactoryNotMergeableException, indicating pre-aggregated inputs cannot be merged under one aggregator spec.

Source

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

   * by the "other" aggregator factory, and we want to do some additional combining of them. This happens, for example,
   * when compacting two segments together that both have a metric column with the same name. (Even though the name of
   * the column is the same, the aggregator factory used to create it may be different from segment to segment.)
   *
   * This method may throw {@link AggregatorFactoryNotMergeableException}, meaning that "this" and "other" are not
   * compatible and values from one cannot sensibly be combined with values from the other.
   *
   * @return a new Factory that can be used for merging the output of aggregators from this factory and other.
   *
   * @see #getCombiningFactory() which is equivalent to {@code foo.getMergingFactory(foo)} (when "this" and "other"
   * are the same instance).
   */
  public AggregatorFactory getMergingFactory(AggregatorFactory other) throws AggregatorFactoryNotMergeableException
  {
    final AggregatorFactory combiningFactory = this.getCombiningFactory();
    if (other.getName().equals(this.getName()) && combiningFactory.equals(other.getCombiningFactory())) {
      return combiningFactory;
    } else {
      throw new AggregatorFactoryNotMergeableException(this, other);
    }
  }

  /**
   * This was previously used by group-by v1 and will be removed in a future release
   */
  @Deprecated
  public List<AggregatorFactory> getRequiredColumns()
  {
    throw new UnsupportedOperationException(
        "Do not call or implement this method, it is deprecated and will be removed in a future releases."
    );
  }

  /**
   * A method that knows how to "deserialize" the object from whatever form it might have been put into
   * in order to transfer via JSON.
   *

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure both aggregator factories share the same output name and identical combining parameters (type, fieldName/expression)
  2. Inspect the detailed info in the exception message to find the mismatched attribute and align the two specs
  3. Adjust the query or ingestion spec so all merged sources use compatible aggregators

Example fix

// before
new DoubleSumAggregatorFactory("sum", "col1") merged with new DoubleSumAggregatorFactory("sum", "col2")
// after
new DoubleSumAggregatorFactory("sum", "col") merged with new DoubleSumAggregatorFactory("sum", "col")
Defensive patterns

Strategy: validation

Validate before calling

// before merging
if (!a.getName().equals(b.getName()) || !a.getCombiningFactory().equals(b.getCombiningFactory())) {
  throw new IllegalArgumentException("Aggregators not mergeable: " + a.getName() + " vs " + b.getName());
}

Type guard

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

Try / catch

try {
  merged = factory.getMergingFactory(other);
} catch (AggregatorFactoryNotMergeableException e) {
  log.error("Cannot merge aggregators", e);
  throw new IAE("Align aggregator names and parameters across datasources");
}

Prevention

When it happens

Trigger: Calling getMergingFactory(other) where other.getName() differs from this.getName(), or where this.getCombiningFactory() does not equal other.getCombiningFactory() (different aggregator types, different fieldNames, expressions, or parameters).

Common situations: Merging segments/datasources whose schemas declare different aggregators under the same output name; typos in fieldName or different aggregators (doubleSum vs longSum) across datasources; subquery/post-aggregation name mismatches.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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