{"record":{"id":"9ebd72fb3c5c2671","repo":"apache/druid","slug":"cannot-return-double-for-null-value","errorCode":null,"errorMessage":"Cannot return double for Null Value","messagePattern":"Cannot return double for Null Value","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/aggregation/NullableNumericAggregateCombiner.java","lineNumber":85,"sourceCode":"        delegate.fold(selector);\n      }\n    }\n  }\n\n  @Override\n  public float getFloat()\n  {\n    if (isNullResult) {\n      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  }","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/NullableNumericAggregateCombiner.java#L67-L103","documentation":"Same mechanism as the float variant: NullableNumericAggregateCombiner tracks a null combined result and getDouble() must return a primitive double, which cannot encode null. It throws IllegalStateException rather than silently returning 0.0. The caller is required to check isNull() first.","triggerScenarios":"Calling getDouble() while isNullResult is true — after reset() on a null selector value with no non-null fold() since — in a query where SQL-compatible null handling (druid.generic.useDefaultValueForNull=false) is enabled and every input value in the group was null.","commonSituations":"All-null groups for a SUM/AVG-style aggregator read through a custom result accessor; extension code that copies combiner values into result rows assuming non-null primitives; result-format or type-conversion paths written before null-aware combiners were introduced.","solutions":["Check combiner.isNull() (or selector.isNull()) before calling getDouble() and represent the result as a nullable Double.","Prefer getObject() which returns null instead of throwing for null results.","Enable druid.generic.useDefaultValueForNull=true or wrap the expression in COALESCE if the consumer cannot represent null.","Audit custom accessors/serializers to handle null-aware combiners added with SQL null handling."],"exampleFix":"// before\ndouble value = combiner.getDouble();\n// after\nDouble value = combiner.isNull() ? null : combiner.getDouble();","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 Double safeGetDouble(AggregateCombiner<?> combiner) {\n  return combiner.isNull() ? null : combiner.getDouble();\n}","tryCatchPattern":"try {\n  double v = combiner.getDouble();\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 every primitive getter on AggregateCombiner implementations.","Use boxed accessors (getObject) for code paths that must model SQL NULL.","Test aggregations over all-null groups explicitly when null handling is SQL-compatible.","COALESCE in SQL or enable default-value-for-null mode if nulls must be flattened."],"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"}