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
- Check the object for null before calling fromObj and skip/default the row instead
- Fix the ingestion spec so the HLL metric column is present and serialized for all rows
- 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
- Null-check aggregator column values before deserialization
- Ensure ingestion specs always serialize the sketch metric
- Wrap fromObj calls in a small utility that defaults nulls to an empty sketch
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
- Object is not of a type[%s] that can be deserialized to sket
- Not implemented
- Invalid input [%s] of type [%s] for [%s] aggregator [%s]
- Not implemented
- Unsupported type %s
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/8c40b868054bba09.
Report an issue: GitHub.