apache/druid · error · IllegalStateException
Cannot return double for Null Value
Error message
Cannot return double for Null Value
What it means
NullableNumericBufferAggregator's getDouble() inspects the null-marker byte stored before each double value in the ByteBuffer and throws IllegalStateException if the stored value is null. This preserves Druid's explicit null semantics instead of coercing null to 0.0 or NaN.
Source
Thrown at processing/src/main/java/org/apache/druid/query/aggregation/NullableNumericBufferAggregator.java:111
throw new IllegalStateException("Cannot return float for Null Value");
}
return delegate.getFloat(buf, position + Byte.BYTES);
}
@Override
public long getLong(ByteBuffer buf, int position)
{
if (buf.get(position) == TypeStrategies.IS_NULL_BYTE) {
throw new IllegalStateException("Cannot return long for Null Value");
}
return delegate.getLong(buf, position + Byte.BYTES);
}
@Override
public double getDouble(ByteBuffer buf, int position)
{
if (buf.get(position) == TypeStrategies.IS_NULL_BYTE) {
throw new IllegalStateException("Cannot return double for Null Value");
}
return delegate.getDouble(buf, position + Byte.BYTES);
}
@Override
public boolean isNull(ByteBuffer buf, int position)
{
return buf.get(position) == TypeStrategies.IS_NULL_BYTE || delegate.isNull(buf, position + Byte.BYTES);
}
@Override
public void relocate(int oldPosition, int newPosition, ByteBuffer oldBuffer, ByteBuffer newBuffer)
{
delegate.relocate(oldPosition + Byte.BYTES, newPosition + Byte.BYTES, oldBuffer, newBuffer);
}
@Override
public void close()View on GitHub (pinned to 9b90983fd2)
Solutions
- Query agg.isNull(buf, position) first and handle the null branch
- Confirm all delegate calls offset by position + Byte.BYTES to account for the flag byte
- Check relocate() copies both the marker byte and the value when buffers are reorganized
- For legitimately null groups, handle null in the result-extraction layer rather than reading the primitive
Example fix
// before double v = agg.getDouble(buf, position); // after double v = agg.isNull(buf, position) ? Double.NaN /* or handle null */ : agg.getDouble(buf, position);
Defensive patterns
Strategy: validation
Validate before calling
if (agg.isNull(buf, position)) {
return null;
} Try / catch
try {
return agg.getDouble(buf, position);
} catch (IllegalStateException e) {
if (e.getMessage().contains("Cannot return double for Null Value")) {
return null;
}
throw e;
} Prevention
- Check the null flag before every primitive buffer read
- Keep relocate()/copy logic moving flag byte and value together
- Verify buffer-size math includes the extra null-flag byte
- Add tests exercising all-null groups and buffer reorganization paths
When it happens
Trigger: Calling getDouble(buf, position) where the null-flag byte at `position` equals TypeStrategies.IS_NULL_BYTE (group aggregated only null inputs).
Common situations: Double-typed group-by aggregations with all-null groups; buffer-alignment bugs (forgot Byte.BYTES offset when delegating); buffer corruptions from incorrect relocate()/copy logic moving value bytes without flag bytes.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Cannot return float for Null Value
- Cannot return long for Null Value
- Cannot return float for Null Value
- Cannot return long for Null Value
- Cannot return double for Null Value
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/55046da1a0d73d8f.
Report an issue: GitHub.