apache/druid · error · IllegalStateException
Cannot return primitive float for Null Value
Error message
Cannot return primitive float for Null Value
What it means
NullableNumericAggregateCombiner wraps a non-null-aware AggregateCombiner when SQL-compatible null handling is enabled. It tracks whether the combined result is null; since getFloat() returns a primitive float, there is no way to represent null, so it throws IllegalStateException rather than return a meaningless default (e.g. 0.0). Callers must check isNull() before calling the primitive getters.
Source
Thrown at processing/src/main/java/org/apache/druid/query/aggregation/NullableNumericAggregateCombiner.java:76
@Override
public void fold(ColumnValueSelector selector)
{
boolean isNotNull = !selector.isNull();
if (isNotNull) {
if (isNullResult) {
isNullResult = false;
delegate.reset(selector);
} else {
delegate.fold(selector);
}
}
}
@Override
public float getFloat()
{
if (isNullResult) {
throw new IllegalStateException("Cannot return primitive float for Null Value");
}
return delegate.getFloat();
}
@Override
public double getDouble()
{
if (isNullResult) {
throw new IllegalStateException("Cannot return double for Null Value");
}
return delegate.getDouble();
}
@Override
public long getLong()
{
if (isNullResult) {
throw new IllegalStateException("Cannot return long for Null Value");View on GitHub (pinned to 9b90983fd2)
Solutions
- Call isNull() on the AggregateCombiner/ColumnValueSelector before invoking getFloat() and handle the null case (return null in the result row or skip).
- Use getObject() instead of getFloat(); it returns null for null results instead of throwing.
- If the caller cannot handle nulls, enable druid.generic.useDefaultValueForNull=true so nulls become 0-typed defaults, or coalesce the column in SQL (COALESCE).
- Fix custom accessor code that mixes null-aware combiners with primitive-only extraction paths.
Example fix
// before float value = combiner.getFloat(); // after Float value = combiner.isNull() ? null : combiner.getFloat();
Defensive patterns
Strategy: type-guard
Validate before calling
// call-site guard: never read primitives from a null-aware combiner unchecked
if (combiner.isNull()) {
return null; // or sentinel per your result model
} Type guard
static Float safeGetFloat(AggregateCombiner<?> combiner) {
return combiner.isNull() ? null : combiner.getFloat();
} Try / catch
try {
float v = combiner.getFloat();
} catch (IllegalStateException e) {
if (e.getMessage() != null && e.getMessage().contains("Null Value")) {
// treat as SQL NULL
return null;
}
throw e;
} Prevention
- Always pair primitive getters (getFloat/getDouble/getLong) with an isNull() check on null-aware combiners.
- Prefer getObject()/boxed accessors when writing result-extraction code that must handle SQL NULL.
- Run with druid.generic.useDefaultValueForNull=false in CI to surface unguarded null paths in custom code.
- COALESCE nullable columns in SQL when downstream consumers cannot represent null.
When it happens
Trigger: Calling getFloat() on a NullableNumericAggregateCombiner after reset() observed a null selector value and no subsequent fold() call supplied a non-null value, i.e. isNullResult == true. This happens when aggregation result extraction code reads a float directly without consulting isNull() first.
Common situations: Custom extension code or a custom SQL accessor reading aggregator results; all input rows for the aggregation group had null values under druid.generic.useDefaultValueForNull=false; a post-aggregation or result-format path that assumes primitives are always non-null.
Related errors
- Cannot return double for Null Value
- Cannot return long for Null Value
- Emit called unexpectedly before service start
- Got an exception while parsing file [%s]
- Unable to copy key [%s] to file [%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/1c244a62d9e8c53a.
Report an issue: GitHub.