apache/druid · error · org.apache.druid.java.util.common.IAE

lhs[ ] or rhs[ ] not of type [ ]

Error message

lhs[%s] or rhs[%s] not of type [%s]

What it means

DoubleMeanAggregatorFactory.combine() only merges two DoubleMeanHolder instances via update(). If either side is a different type (raw Double, byte[], String, null), the invariant that both inputs are the aggregator's own output type is broken, so it throws an IllegalArgumentException naming the offending classes.

Solutions

  1. Ensure every input passed to combine() is first run through DoubleMeanAggregatorFactory.deserialize() so byte[]/base64-String forms become DoubleMeanHolder.
  2. Verify all segments for the metric were ingested with the doubleMean aggregator type; re-ingest mismatched segments.
  3. Convert raw values yourself: DoubleMeanHolder.fromBytes(...) for byte[], or wrap a double mean/count into a DoubleMeanHolder before combining.

Example fix

// before
Object merged = factory.combine(rawA, rawB);
// after
DoubleMeanAggregatorFactory f = ...;
Object merged = f.combine(f.deserialize(rawA), f.deserialize(rawB));
Defensive patterns

Strategy: validation

Validate before calling

if (!(lhs instanceof DoubleMeanHolder) || !(rhs instanceof DoubleMeanHolder)) { throw new IllegalArgumentException("combine inputs must be DoubleMeanHolder; run deserialize() first"); }

Type guard

boolean isCombinnable(Object l, Object r) { return l instanceof DoubleMeanHolder && r instanceof DoubleMeanHolder; }

Try / catch

try { return factory.combine(lhs, rhs); } catch (IllegalArgumentException e) { return factory.combine(factory.deserialize(lhs), factory.deserialize(rhs)); }

Prevention

When it happens

Trigger: Combine-time (shuffling/merging partial results) where an input value was produced by a different aggregator, deserialized without going through deserialize(), or is null/raw Double from intermediate storage.

Common situations: Mixed aggregator types under the same field name across segments; results combined after skipping intermediate deserialization; custom code feeding raw doubles into the factory's combine instead of holders; cache entries written by an older Druid version using a different intermediate format.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/aggregation/mean/DoubleMeanAggregatorFactory.java:155

  {
    final ColumnCapabilities capabilities = columnInspector.getColumnCapabilities(fieldName);
    return capabilities == null || capabilities.isNumeric();
  }

  @Override
  public Comparator getComparator()
  {
    return DoubleMeanHolder.COMPARATOR;
  }

  @Nullable
  @Override
  public Object combine(@Nullable Object lhs, @Nullable Object rhs)
  {
    if (lhs instanceof DoubleMeanHolder && rhs instanceof DoubleMeanHolder) {
      return ((DoubleMeanHolder) lhs).update((DoubleMeanHolder) rhs);
    } else {
      throw new IAE(
          "lhs[%s] or rhs[%s] not of type [%s]",
          Utils.safeObjectClassGetName(lhs),
          Utils.safeObjectClassGetName(rhs),
          DoubleMeanHolder.class.getName()
      );
    }
  }

  @Override
  public AggregatorFactory getCombiningFactory()
  {
    return new DoubleMeanAggregatorFactory(name, name);
  }

  @Override
  public Object deserialize(Object object)
  {
    if (object instanceof byte[]) {

View on GitHub (pinned to 9b90983fd2)