{"record":{"id":"0f3327d457221cdd","repo":"apache/druid","slug":"lhs-s-or-rhs-s-not-of-type-s","errorCode":null,"errorMessage":"lhs[%s] or rhs[%s] not of type [%s]","messagePattern":"lhs\\[(.+?)\\] or rhs\\[(.+?)\\] not of type \\[(.+?)\\]","errorType":"exception","errorClass":"org.apache.druid.java.util.common.IAE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/aggregation/mean/DoubleMeanAggregatorFactory.java","lineNumber":155,"sourceCode":"  {\n    final ColumnCapabilities capabilities = columnInspector.getColumnCapabilities(fieldName);\n    return capabilities == null || capabilities.isNumeric();\n  }\n\n  @Override\n  public Comparator getComparator()\n  {\n    return DoubleMeanHolder.COMPARATOR;\n  }\n\n  @Nullable\n  @Override\n  public Object combine(@Nullable Object lhs, @Nullable Object rhs)\n  {\n    if (lhs instanceof DoubleMeanHolder && rhs instanceof DoubleMeanHolder) {\n      return ((DoubleMeanHolder) lhs).update((DoubleMeanHolder) rhs);\n    } else {\n      throw new IAE(\n          \"lhs[%s] or rhs[%s] not of type [%s]\",\n          Utils.safeObjectClassGetName(lhs),\n          Utils.safeObjectClassGetName(rhs),\n          DoubleMeanHolder.class.getName()\n      );\n    }\n  }\n\n  @Override\n  public AggregatorFactory getCombiningFactory()\n  {\n    return new DoubleMeanAggregatorFactory(name, name);\n  }\n\n  @Override\n  public Object deserialize(Object object)\n  {\n    if (object instanceof byte[]) {","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/mean/DoubleMeanAggregatorFactory.java#L137-L173","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure every input passed to combine() is first run through DoubleMeanAggregatorFactory.deserialize() so byte[]/base64-String forms become DoubleMeanHolder.","Verify all segments for the metric were ingested with the doubleMean aggregator type; re-ingest mismatched segments.","Convert raw values yourself: DoubleMeanHolder.fromBytes(...) for byte[], or wrap a double mean/count into a DoubleMeanHolder before combining."],"exampleFix":"// before\nObject merged = factory.combine(rawA, rawB);\n// after\nDoubleMeanAggregatorFactory f = ...;\nObject merged = f.combine(f.deserialize(rawA), f.deserialize(rawB));","handlingStrategy":"validation","validationCode":"if (!(lhs instanceof DoubleMeanHolder) || !(rhs instanceof DoubleMeanHolder)) { throw new IllegalArgumentException(\"combine inputs must be DoubleMeanHolder; run deserialize() first\"); }","typeGuard":"boolean isCombinnable(Object l, Object r) { return l instanceof DoubleMeanHolder && r instanceof DoubleMeanHolder; }","tryCatchPattern":"try { return factory.combine(lhs, rhs); } catch (IllegalArgumentException e) { return factory.combine(factory.deserialize(lhs), factory.deserialize(rhs)); }","preventionTips":["Always deserialize intermediate values with the owning AggregatorFactory before combine.","Keep the same doubleMean aggregator type for a field across all ingestion jobs.","Clear caches after changing aggregator types.","Validate partial-result storage format when implementing custom distribution."],"tags":["druid","aggregation","mean","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}