apache/druid · error · IllegalArgumentException

Expected a number or an instance of MergingDigest, but…

Error message

Expected a number or an instance of MergingDigest, but received [%s] of type [%s]

What it means

TDigestSketchBufferAggregator.aggregate() only knows how to fold two input shapes: a raw Number (added as a single value) and an already-built MergingDigest (merged into the sketch). When the selector's getObject() returns any other type, the column does not hold valid t-digest sketch data and aggregation cannot continue, so it throws instead of silently skipping a non-null, non-numeric value.

Solutions

  1. Fix the input so the aggregated column contains numbers or MergingDigest values (e.g. correct the parser/flattener spec)
  2. If ingesting from serialized sketches, ensure the tdigestsketch complex metric serde is used so values deserialized to MergingDigest
  3. Inspect the offending rows and cast or transform non-numeric values before ingestion
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Thrown at extensions-contrib/tdigestsketch/src/main/java/org/apache/druid/query/aggregation/tdigestsketch/TDigestSketchBufferAggregator.java:80 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

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

  {
    MergingDigest emptyDigest = new MergingDigest(compression);
    addToCache(buffer, position, emptyDigest);
  }

  @Override
  public void aggregate(ByteBuffer buffer, int position)
  {
    Object x = selector.getObject();
    if (x == null) {
      return;
    }
    MergingDigest sketch = sketchCache.get(buffer).get(position);
    if (x instanceof Number) {
      sketch.add(((Number) x).doubleValue());
    } else if (x instanceof MergingDigest) {
      sketch.add((MergingDigest) x);
    } else {
      throw new IAE(
          "Expected a number or an instance of MergingDigest, but received [%s] of type [%s]",
          x,
          x.getClass()
      );
    }
  }

  @Override
  public Object get(final ByteBuffer buffer, final int position)
  {
    // sketchCache is an IdentityHashMap where the reference of buffer is used for equality checks.
    // So the returned object isn't impacted by the changes in the buffer object made by concurrent threads.
    return sketchCache.get(buffer).get(position);
  }

  @Override
  public float getFloat(final ByteBuffer buffer, final int position)
  {

View on GitHub (pinned to 9b90983fd2)