{"record":{"id":"bf597d54cedb05ed","repo":"apache/druid","slug":"incompatible-aggregator-factories-this-and-oth","errorCode":null,"errorMessage":"Incompatible aggregator factories, [this] and [other]","messagePattern":"Incompatible aggregator factories, \\[this\\] and \\[other\\]","errorType":"exception","errorClass":"org.apache.druid.query.aggregation.AggregatorFactoryNotMergeableException","httpStatus":null,"severity":"error","filePath":"extensions-core/histogram/src/main/java/org/apache/druid/query/aggregation/histogram/ApproximateHistogramAggregatorFactory.java","lineNumber":211,"sourceCode":"\n  @Override\n  public AggregatorFactory getMergingFactory(AggregatorFactory other) throws AggregatorFactoryNotMergeableException\n  {\n    if (other.getName().equals(this.getName()) && other instanceof ApproximateHistogramAggregatorFactory) {\n      ApproximateHistogramAggregatorFactory castedOther = (ApproximateHistogramAggregatorFactory) other;\n\n      return new ApproximateHistogramFoldingAggregatorFactory(\n          name,\n          name,\n          Math.max(resolution, castedOther.resolution),\n          numBuckets,\n          Math.min(lowerLimit, castedOther.lowerLimit),\n          Math.max(upperLimit, castedOther.upperLimit),\n          finalizeAsBase64Binary\n      );\n\n    } else {\n      throw new AggregatorFactoryNotMergeableException(this, other);\n    }\n  }\n\n  @Override\n  public Object deserialize(Object object)\n  {\n    if (object instanceof byte[]) {\n      final ApproximateHistogram ah = ApproximateHistogram.fromBytes((byte[]) object);\n      ah.setLowerLimit(lowerLimit);\n      ah.setUpperLimit(upperLimit);\n\n      return ah;\n    } else if (object instanceof ByteBuffer) {\n      final ApproximateHistogram ah = ApproximateHistogram.fromBytes((ByteBuffer) object);\n      ah.setLowerLimit(lowerLimit);\n      ah.setUpperLimit(upperLimit);\n\n      return ah;","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/histogram/src/main/java/org/apache/druid/query/aggregation/histogram/ApproximateHistogramAggregatorFactory.java#L193-L229","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nAggregatorFactory a = new ApproximateHistogramAggregatorFactory(\"out\", \"col\", ...);\nAggregatorFactory b = new DoubleSumAggregatorFactory(\"out\", \"col\"); // merge throws\n// after\nAggregatorFactory a = new ApproximateHistogramAggregatorFactory(\"hist\", \"col\", ...);\nAggregatorFactory b = new DoubleSumAggregatorFactory(\"sum\", \"col\");","handlingStrategy":"validation","validationCode":"if (!aggregationNameToFactory.isEmpty() && new Set(aggregationNames).size !== aggregationNames.length) {\n  throw new IllegalArgumentException(\"Duplicate aggregation output names cause merge failures\");\n}","typeGuard":"null","tryCatchPattern":"try {\n  merged = factory.getMergingFactory(other);\n} catch (AggregatorFactoryNotMergeableException e) {\n  log.error(\"Aggregation output names must be unique and same-typed across nodes\", e);\n  throw e;\n}","preventionTips":["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"],"tags":["aggregation","merge","incompatible-types","query"],"backgroundTag":"incompatible-source-type","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"}