apache/druid · error · org.apache.druid.query.aggregation.AggregatorFactoryNotMergeableException
Incompatible aggregator factories, [this] and [other]
Error message
Incompatible aggregator factories, [this] and [other]
What it means
ApproximateHistogramAggregatorFactory.getMergingFactory() can only merge factories of the same runtime type and compatible parameters. When the incoming factory is not an ApproximateHistogramAggregatorFactory (or the cast fails the equality checks), it throws AggregatorFactoryNotMergeableException with the message 'Incompatible aggregator factories'. Two differently-typed aggregations over the same output name cannot be merged in distributed query results.
Source
Thrown at extensions-core/histogram/src/main/java/org/apache/druid/query/aggregation/histogram/ApproximateHistogramAggregatorFactory.java:211
@Override
public AggregatorFactory getMergingFactory(AggregatorFactory other) throws AggregatorFactoryNotMergeableException
{
if (other.getName().equals(this.getName()) && other instanceof ApproximateHistogramAggregatorFactory) {
ApproximateHistogramAggregatorFactory castedOther = (ApproximateHistogramAggregatorFactory) other;
return new ApproximateHistogramFoldingAggregatorFactory(
name,
name,
Math.max(resolution, castedOther.resolution),
numBuckets,
Math.min(lowerLimit, castedOther.lowerLimit),
Math.max(upperLimit, castedOther.upperLimit),
finalizeAsBase64Binary
);
} else {
throw new AggregatorFactoryNotMergeableException(this, other);
}
}
@Override
public Object deserialize(Object object)
{
if (object instanceof byte[]) {
final ApproximateHistogram ah = ApproximateHistogram.fromBytes((byte[]) object);
ah.setLowerLimit(lowerLimit);
ah.setUpperLimit(upperLimit);
return ah;
} else if (object instanceof ByteBuffer) {
final ApproximateHistogram ah = ApproximateHistogram.fromBytes((ByteBuffer) object);
ah.setLowerLimit(lowerLimit);
ah.setUpperLimit(upperLimit);
return ah;View on GitHub (pinned to 9b90983fd2)
Solutions
- Rename one of the aggregations so output names are unique (e.g. 'hist' vs 'sum')
- Ensure both sides of the merge use identical aggregator factory type and parameters (resolution, lowerLimit, upperLimit)
- Check queries for aggregation name collisions with post-aggregators or nested subquery columns
- If a rolling upgrade caused mismatched plans, align Druid versions/configs across nodes
Example fix
// before
AggregatorFactory a = new ApproximateHistogramAggregatorFactory("out", "col", ...);
AggregatorFactory b = new DoubleSumAggregatorFactory("out", "col"); // merge throws
// after
AggregatorFactory a = new ApproximateHistogramAggregatorFactory("hist", "col", ...);
AggregatorFactory b = new DoubleSumAggregatorFactory("sum", "col"); Defensive patterns
Strategy: validation
Validate before calling
if (!aggregationNameToFactory.isEmpty() && new Set(aggregationNames).size !== aggregationNames.length) {
throw new IllegalArgumentException("Duplicate aggregation output names cause merge failures");
} Type guard
null
Try / catch
try {
merged = factory.getMergingFactory(other);
} catch (AggregatorFactoryNotMergeableException e) {
log.error("Aggregation output names must be unique and same-typed across nodes", e);
throw e;
} Prevention
- Keep aggregation output names unique within a query, including post-aggregators
- Use identical aggregator factories (type and parameters) on both sides of a merge
- Review nested/subquery columns for name collisions
- Keep query engine versions consistent across historical nodes
When it happens
Trigger: getMergingFactory(other) is called where other's equality check against this factory fails — e.g. merging results from two nodes that aggregated the same output name with different aggregation types (approxHistogram vs another aggregator type).
Common situations: Two subqueries/hashes producing aggregations with the same output column name but different types; a groupBy or timeseries with a post-aggregation name colliding with an aggregation name; mismatched query plans across historical nodes after a config/version change.
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
- AggregatorFactoryNotMergeableException(this, other)
- [%s] does not implement makeAggregateCombiner()
- can't merge [%s : %s] and [%s : %s] , with detailed info [%s
- AggregatorFactoryNotMergeableException
- Query error, cancelling pending results for query [%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/bf597d54cedb05ed.
Report an issue: GitHub.