apache/druid · error · NullPointerException

HllSketchHolder.fromObj cannot take a null argument

Error message

HllSketchHolder.fromObj cannot take a null argument

What it means

HllSketchHolder.fromObj is the deserialization entry point for HLL sketch aggregation objects and explicitly rejects null input with a NullPointerException. The library requires callers to pass a HllSketchHolder, HllSketch, Memory, or base64 String; null carries no recoverable meaning. Throwing early makes upstream data-pipeline bugs (e.g. missing aggregator rows) fail fast instead of corrupting results.

Source

Thrown at extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/hll/HllSketchHolder.java:35

 * under the License.
 */

package org.apache.druid.query.aggregation.datasketches.hll;

import com.fasterxml.jackson.annotation.JsonValue;
import org.apache.datasketches.hll.HllSketch;
import org.apache.datasketches.hll.TgtHllType;
import org.apache.datasketches.hll.Union;
import org.apache.datasketches.memory.Memory;
import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.StringUtils;

public class HllSketchHolder
{
  public static HllSketchHolder fromObj(Object obj)
  {
    if (obj == null) {
      throw new NullPointerException("HllSketchHolder.fromObj cannot take a null argument");
    }

    if (obj instanceof HllSketchHolder) {
      return (HllSketchHolder) obj;
    } else if (obj instanceof HllSketch) {
      return HllSketchHolder.of((HllSketch) obj);
    } else if (obj instanceof Union) {
      return HllSketchHolder.of((Union) obj);
    } else if (obj instanceof byte[]) {
      return HllSketchHolder.of(HllSketch.heapify((byte[]) obj));
    } else if (obj instanceof Memory) {
      return HllSketchHolder.of(HllSketch.wrap((Memory) obj));
    } else if (obj instanceof String) {
      return HllSketchHolder.of(HllSketch.heapify(StringUtils.decodeBase64(StringUtils.toUtf8((String) obj))));
    }

    throw new ISE("Object is not of a type[%s] that can be deserialized to sketch.", obj.getClass());
  }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Check the object for null before calling fromObj and skip/default the row instead
  2. Fix the ingestion spec so the HLL metric column is present and serialized for all rows
  3. If null is legitimate, wrap the call and treat null as an empty sketch (HllSketchHolder.of(new HllSketch(...)) or a zeros-filled result)

Example fix

// before
HllSketchHolder holder = HllSketchHolder.fromObj(row.get("sketch"));
// after
Object obj = row.get("sketch");
HllSketchHolder holder = obj == null ? HllSketchHolder.of(new HllSketch(12)) : HllSketchHolder.fromObj(obj);
Defensive patterns

Strategy: type-guard

Validate before calling

if (obj == null) { throw new IllegalArgumentException("sketch column value is null"); }

Type guard

boolean isUsableSketchInput(Object o) { return o instanceof HllSketchHolder || o instanceof HllSketch || o instanceof Memory || o instanceof String; }

Try / catch

try { holder = HllSketchHolder.fromObj(obj); } catch (NullPointerException e) { holder = HllSketchHolder.of(new HllSketch(12)); }

Prevention

When it happens

Trigger: Calling HllSketchHolder.fromObj(null) directly, or indirectly when an aggregation selector/row returns null for a sketch column (e.g. deserializing a null aggregator value from a segment or query result).

Common situations: Reading Druid segments where the HLL metric column is absent for some rows; passing a null combined-aggregator value into a post-aggregator; custom aggregation code that forwards raw column objects without null checks.

Related errors


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