{"record":{"id":"9fd4ecc497643f94","repo":"apache/druid","slug":"cannot-return-long-for-null-value","errorCode":null,"errorMessage":"Cannot return long for Null Value","messagePattern":"Cannot return long for Null Value","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/aggregation/NullableNumericAggregateCombiner.java","lineNumber":94,"sourceCode":"      throw new IllegalStateException(\"Cannot return primitive float for Null Value\");\n    }\n    return delegate.getFloat();\n  }\n\n  @Override\n  public double getDouble()\n  {\n    if (isNullResult) {\n      throw new IllegalStateException(\"Cannot return double for Null Value\");\n    }\n    return delegate.getDouble();\n  }\n\n  @Override\n  public long getLong()\n  {\n    if (isNullResult) {\n      throw new IllegalStateException(\"Cannot return long for Null Value\");\n    }\n    return delegate.getLong();\n  }\n\n  @Override\n  public boolean isNull()\n  {\n    return isNullResult || delegate.isNull();\n  }\n\n  @Nullable\n  @Override\n  public T getObject()\n  {\n    return isNullResult ? null : delegate.getObject();\n  }\n\n  @Override","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/NullableNumericAggregateCombiner.java#L76-L112","documentation":"The long variant of the null-guard in NullableNumericAggregateCombiner: getLong() returns a primitive long that cannot represent SQL NULL, so when the tracked combined result is null it throws IllegalStateException instead of returning a default. Callers must test isNull() first or use the nullable getObject().","triggerScenarios":"Calling getLong() while isNullResult is true — reset() saw a null selector and no non-null value has been folded in — typically in queries with SQL-compatible null handling where all rows contributing to the group contained null for the aggregated column.","commonSituations":"Long-typed aggregators (e.g. longSum) over an entirely null group read by custom extraction code; COUNT/SUM result handling written assuming primitive defaults; extension aggregator implementations built on AggregateCombiner that ignore the null-aware wrapper.","solutions":["Guard with combiner.isNull() before calling getLong() and emit a nullable Long (or skip the value) when true.","Use getObject() to receive a boxed Long that is null instead of an exception.","Enable druid.generic.useDefaultValueForNull=true or use COALESCE in the SQL query if null semantics must be flattened to 0.","Update custom result extraction code to be null-aware for all primitive accessors (getFloat/getDouble/getLong)."],"exampleFix":"// before\nlong value = combiner.getLong();\n// after\nLong value = combiner.isNull() ? null : combiner.getLong();","handlingStrategy":"type-guard","validationCode":"// call-site guard: never read primitives from a null-aware combiner unchecked\nif (combiner.isNull()) {\n  return null; // or sentinel per your result model\n}","typeGuard":"static Long safeGetLong(AggregateCombiner<?> combiner) {\n  return combiner.isNull() ? null : combiner.getLong();\n}","tryCatchPattern":"try {\n  long v = combiner.getLong();\n} catch (IllegalStateException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Null Value\")) {\n    // treat as SQL NULL\n    return null;\n  }\n  throw e;\n}","preventionTips":["Check isNull() before calling getLong() on null-aware combiners.","Use getObject() (boxed Long) wherever SQL NULL must be representable.","Cover all-null input groups in integration tests for long aggregators.","Normalize nulls with COALESCE or druid.generic.useDefaultValueForNull=true for primitive-only consumers."],"tags":["druid","aggregation","null-handling","sql","state"],"backgroundTag":"null-argument","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}