apache/druid · error · AggregatorFactoryNotMergeableException

AggregatorFactoryNotMergeableException

Error message

AggregatorFactoryNotMergeableException

What it means

AggregatorFactory.getMergingFactory requires that the two factories merge into one: same name and same concrete class. TDDigestSketchAggregatorFactory throws AggregatorFactoryNotMergeableException when the other factory differs in name or class, meaning query-level merging cannot combine the two aggregations.

Source

Thrown at extensions-contrib/tdigestsketch/src/main/java/org/apache/druid/query/aggregation/tdigestsketch/TDigestSketchAggregatorFactory.java:179

    }
    TDigest union = (TDigest) lhs;
    union.add((TDigest) rhs);
    return union;
  }

  @Override
  public AggregatorFactory getCombiningFactory()
  {
    return new TDigestSketchAggregatorFactory(name, name, compression, tDigestConfig);
  }

  @Override
  public AggregatorFactory getMergingFactory(AggregatorFactory other) throws AggregatorFactoryNotMergeableException
  {
    if (other.getName().equals(this.getName()) && this.getClass() == other.getClass()) {
      return getCombiningFactory();
    } else {
      throw new AggregatorFactoryNotMergeableException(this, other);
    }
  }

  @Override
  public Object deserialize(Object serializedSketch)
  {
    return TDigestSketchUtils.deserialize(serializedSketch);
  }

  @Nullable
  @Override
  public Object finalizeComputation(@Nullable Object object)
  {
    return object;
  }

  @Override
  @JsonProperty

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure both aggregators share the same output name and the same factory class (both TDigestSketchAggregatorFactory) with identical parameters.
  2. Fix the query so the tdigestsketch aggregator is not merged with an incompatible aggregator type; use separate output names for separate aggregations.
  3. Align the SQL/native query specs across broker and historicals so the same factory is generated on each side.
  4. If thrown from a custom extension, implement/verify getCombiningFactory for the pair.

Example fix

// before
AggregatorFactory a = new TDigestSketchAggregatorFactory("sk1", "col", 100);
AggregatorFactory b = new DoubleSumAggregatorFactory("sk1", "col");
// after
AggregatorFactory a = new TDigestSketchAggregatorFactory("sk1", "col", 100);
AggregatorFactory b = new TDigestSketchAggregatorFactory("sk1", "col", 100); // same name and type
Defensive patterns

Strategy: try-catch

Validate before calling

if (!other.getName().equals(this.getName()) || other.getClass() != this.getClass()) { throw new IllegalArgumentException("aggregators not mergeable: " + this + " vs " + other); }

Try / catch

try { merged = factory.getMergingFactory(other); } catch (AggregatorFactoryNotMergeableException e) { log.error("Cannot merge aggregators %s and %s; check query aliases/types", e); }

Prevention

When it happens

Trigger: Merging query results where sub-queries or the broker combine aggregator factories: one factory named differently (e.g. aliased output name) or of a different class (tdigest vs doubleSum) is passed to getMergingFactory.

Common situations: SQL planner producing mismatched aggregator aliases for the same underlying column; combining a tdigestsketch aggregator with another aggregator type on the same metric; distributed query merge across brokers with differing query specs.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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