{"record":{"id":"7cde687c045949dc","repo":"apache/druid","slug":"aggregatorfactorynotmergeableexception-7cde68","errorCode":null,"errorMessage":"AggregatorFactoryNotMergeableException","messagePattern":"AggregatorFactoryNotMergeableException","errorType":"exception","errorClass":"AggregatorFactoryNotMergeableException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/aggregation/SimpleDoubleAggregatorFactory.java","lineNumber":196,"sourceCode":"  {\n    return object;\n  }\n\n  @Override\n  public List<String> requiredFields()\n  {\n    return fieldName != null\n           ? Collections.singletonList(fieldName)\n           : fieldExpression.get().analyzeInputs().getRequiredBindingsList();\n  }\n\n  @Override\n  public AggregatorFactory getMergingFactory(AggregatorFactory other) throws AggregatorFactoryNotMergeableException\n  {\n    if (other.getName().equals(this.getName()) && this.getClass() == other.getClass()) {\n      return getCombiningFactory();\n    } else {\n      throw new AggregatorFactoryNotMergeableException(this, other);\n    }\n  }\n\n  @Override\n  public int hashCode()\n  {\n    return Objects.hash(fieldName, expression, name);\n  }\n\n  @Override\n  public boolean equals(Object o)\n  {\n    if (this == o) {\n      return true;\n    }\n    if (o == null || getClass() != o.getClass()) {\n      return false;\n    }","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/SimpleDoubleAggregatorFactory.java#L178-L214","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure both aggregation sides use the same output name for the double aggregator","Ensure both sides use the same aggregator type (doubleSum/doubleMin/doubleMax/doubleFirst etc.) so classes match","Rewrite the query so subquery and outer aggregations are consistent, or remove the merging requirement by pushing aggregations into the inner query","If data was ingested with an older schema, re-ingest or use a query that avoids cross-shard merge of mismatched factories"],"exampleFix":"// before\n Aggregations: aggColumnAggregate: { type: \"doubleSum\", name: \"sum_x\" } and { type: \"longSum\", name: \"sum_x\" }\n// after\n Use consistent factories:\n { type: \"doubleSum\", name: \"sum_x\" } on both subquery and outer query","handlingStrategy":"validation","validationCode":"boolean mergeable(AggregatorFactory a, AggregatorFactory b) {\n  return a.getName().equals(b.getName()) && a.getClass() == b.getClass();\n}","typeGuard":"boolean isMergeableDoublePair(AggregatorFactory other, SimpleDoubleAggregatorFactory self) {\n  return other instanceof SimpleDoubleAggregatorFactory && other.getName().equals(self.getName());\n}","tryCatchPattern":"try {\n  AggregatorFactory merged = factory.getMergingFactory(other);\n} catch (AggregatorFactoryNotMergeableException e) {\n  LOGGER.warn(e, \"Skipping merge for incompatible aggregator factories: %s vs %s\", e.getFactory1(), e.getFactory2());\n}","preventionTips":["Keep aggregator output names unique and consistent across subqueries and outer queries","Use the same aggregator class/type for the same output name everywhere in a query","Test distributed (multi-segment) execution of complex queries, not just single-segment","After schema changes, verify historical segments match current metric types"],"tags":["aggregation","mergeability","druid"],"backgroundTag":"aggregator-factory-not-mergeable","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}