{"record":{"id":"747c8cdc77c51b0f","repo":"apache/druid","slug":"aggregatorfactorynotmergeableexception-this-other-747c8c","errorCode":null,"errorMessage":"AggregatorFactoryNotMergeableException(this, other)","messagePattern":"AggregatorFactoryNotMergeableException\\(this, other\\)","errorType":"exception","errorClass":"AggregatorFactoryNotMergeableException","httpStatus":500,"severity":"error","filePath":"extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/quantiles/DoublesSketchAggregatorFactory.java","lineNumber":387,"sourceCode":"  public AggregatorFactory getMergingFactory(AggregatorFactory other) throws AggregatorFactoryNotMergeableException\n  {\n    if (other.getName().equals(this.getName()) && other instanceof DoublesSketchAggregatorFactory) {\n      final DoublesSketchAggregatorFactory castedOther = (DoublesSketchAggregatorFactory) other;\n\n      if (castedOther.shouldFinalize == shouldFinalize) {\n        // DoublesUnion supports inputs with different k.\n        // The result will have effective k between the specified k and the minimum k from all input sketches\n        // to achieve higher accuracy as much as possible.\n        return new DoublesSketchMergeAggregatorFactory(\n            name,\n            Math.max(k, castedOther.k),\n            Math.max(maxStreamLength, castedOther.maxStreamLength),\n            shouldFinalize\n        );\n      }\n    }\n\n    throw new AggregatorFactoryNotMergeableException(this, other);\n  }\n\n  @Nullable\n  @Override\n  public Object finalizeComputation(@Nullable final Object object)\n  {\n    if (!shouldFinalize || object == null) {\n      return object;\n    }\n\n    return ((DoublesSketch) object).getN();\n  }\n\n  /**\n   * actual type is {@link DoublesSketch}\n   */\n  @Override\n  public ColumnType getIntermediateType()","sourceCodeStart":369,"sourceCodeEnd":405,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/quantiles/DoublesSketchAggregatorFactory.java#L369-L405","documentation":"Druid's mergeable-aggregator protocol requires getMergingFactory(other) to return a factory that can merge with this one. When the other factory is not a DoublesSketchAggregatorFactory (different concrete type), the factory throws AggregatorFactoryNotMergeableException. This protects the sketch union from combining incompatible aggregations.","triggerScenarios":"Calling getMergingFactory with an AggregatorFactory whose getName() matches but whose concrete type is not DoublesSketchAggregatorFactory, e.g. merging a quantilesDoublesSketch agg with an HllSketch, theta, or plain doubleSum aggregator in the same merge position of a distributed group-by.","commonSituations":"Distributed group-by queries where an outer query re-aggregates a sketch column with a mismatched aggregator type; rewriting queries by hand and swapping the aggregator type in the outer spec; tooling that merges query specs automatically.","solutions":["Use the same quantilesDoublesSketch aggregator type in both the inner and outer query specs for the sketch column","Ensure the two factories being merged have identical names, k, maxStreamLength and shouldFinalize settings","If you only need a finalized metric, finalize the sketch in the inner query instead of re-aggregating with a different type"],"exampleFix":"// before: outer query uses doubleSum over a sketch column\n{\"type\":\"doubleSum\",\"name\":\"sk\",\"fieldName\":\"sk\"}\n// after: merge sketches with the same sketch aggregator\n{\"type\":\"quantilesDoublesSketch\",\"name\":\"sk\",\"fieldName\":\"sk\",\"k\":128}","handlingStrategy":"try-catch","validationCode":"if (!(other instanceof DoublesSketchAggregatorFactory)\n    || !((DoublesSketchAggregatorFactory) other).getName().equals(this.getName())) {\n  throw new IllegalArgumentException(\"Cannot merge: outer aggregator must be a matching quantilesDoublesSketch\");\n}","typeGuard":"boolean mergeable(AggregatorFactory a, AggregatorFactory b) {\n  return a.getName().equals(b.getName()) && a.getClass().equals(b.getClass());\n}","tryCatchPattern":"try {\n  AggregatorFactory merged = factory.getMergingFactory(other);\n} catch (AggregatorFactoryNotMergeableException e) {\n  throw new IllegalStateException(\"Mismatched aggregator types for column \" + factory.getName() + \": \" + e.getMessage());\n}","preventionTips":["Use identical quantilesDoublesSketch aggregator specs (same name, k, maxStreamLength, shouldFinalize) in inner and outer queries","Never re-aggregate a sketch column with plain numeric aggregators like doubleSum","Test distributed group-by plans when changing aggregator types"],"tags":["java","druid","aggregation","merge","sketch"],"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"}