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

Unknown object type [ ]

Error message

Unknown object type [%s]

What it means

DoubleMeanAggregatorFactory.deserialize() reconstructs a DoubleMeanHolder from ByteBuffer, byte[], or base64 String (also passing through existing holders). Any other runtime type cannot originate from this aggregator's serialize() and signals a broken intermediate value, so it throws IAE with the value's class name.

Solutions

  1. Clear the segment result caches (or bump cache identifier/version) after changing aggregator types, then let values be re-populated.
  2. Run the value through finalizeComputation()/deserialize() consistently — only deserialize values produced by DoubleMeanAggregatorFactory.serialize().
  3. Re-ingest or rewrite affected segments so intermediate values are serialized holders.
  4. Wrap raw doubles into a DoubleMeanHolder (or its byte form) before calling deserialize-equivalent paths.

Example fix

// before
Object holder = factory.deserialize(someDouble);
// after
Object holder = (someDouble instanceof Double)
    ? new DoubleMeanHolder((Double) someDouble, 1L)
    : factory.deserialize(someDouble);
Defensive patterns

Strategy: type-guard

Validate before calling

if (object != null && !(object instanceof ByteBuffer) && !(object instanceof byte[]) && !(object instanceof String) && !(object instanceof DoubleMeanHolder)) { throw new IllegalArgumentException("Not a serialized DoubleMeanHolder: " + object.getClass()); }

Type guard

boolean isDeserializable(Object o) { return o == null || o instanceof ByteBuffer || o instanceof byte[] || o instanceof String || o instanceof DoubleMeanHolder; }

Try / catch

try { return factory.deserialize(object); } catch (IllegalArgumentException e) { /* value from wrong aggregator type: re-fetch or re-ingest */ }

Prevention

When it happens

Trigger: Calling deserialize() with a raw Double, Long, Map, or null from segment/cache data not produced by doubleMean serialization — e.g. cache entries from a different aggregator type or hand-built results.

Common situations: Druid cache poisoning after changing the metric's aggregator type without clearing caches; cross-version storage format drift; custom code storing the raw finalized double and later trying to deserialize it.

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/94479aa7c11854c0. Report an issue: GitHub.

Appendix: source

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

  }

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

  @Override
  public Object deserialize(Object object)
  {
    if (object instanceof byte[]) {
      return DoubleMeanHolder.fromBytes((byte[]) object);
    } else if (object instanceof String) {
      return DoubleMeanHolder.fromBytes(StringUtils.decodeBase64(StringUtils.toUtf8((String) object)));
    } else if (object instanceof DoubleMeanHolder) {
      return object;
    } else {
      throw new IAE("Unknown object type [%s]", Utils.safeObjectClassGetName(object));
    }
  }

  @Nullable
  @Override
  public Object finalizeComputation(@Nullable Object object)
  {
    if (object instanceof byte[]) {
      return DoubleMeanHolder.fromBytes((byte[]) object).mean();
    } else if (object instanceof DoubleMeanHolder) {
      return ((DoubleMeanHolder) object).mean();
    } else if (object == null) {
      return null;
    } else {
      throw new IAE("Unknown object type [%s]", object.getClass().getName());
    }
  }

View on GitHub (pinned to 9b90983fd2)