{"record":{"id":"411187f2876d5ad2","repo":"apache/druid","slug":"stringlastaggregator-does-not-support-getfloat","errorCode":null,"errorMessage":"StringLastAggregator does not support getFloat()","messagePattern":"StringLastAggregator does not support getFloat\\(\\)","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregator.java","lineNumber":95,"sourceCode":"\n      if (time >= lastTime) {\n        final String value = DimensionHandlerUtils.convertObjectToString(valueSelector.getObject());\n        lastTime = time;\n        lastValue = StringUtils.fastLooseChop(value, maxStringBytes);\n      }\n    }\n  }\n\n  @Override\n  public Object get()\n  {\n    return new SerializablePairLongString(lastTime, StringUtils.chop(lastValue, maxStringBytes));\n  }\n\n  @Override\n  public float getFloat()\n  {\n    throw new UnsupportedOperationException(\"StringLastAggregator does not support getFloat()\");\n  }\n\n  @Override\n  public long getLong()\n  {\n    throw new UnsupportedOperationException(\"StringLastAggregator does not support getLong()\");\n  }\n\n  @Override\n  public double getDouble()\n  {\n    throw new UnsupportedOperationException(\"StringLastAggregator does not support getDouble()\");\n  }\n\n  @Override\n  public void close()\n  {\n    // no resources to cleanup","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregator.java#L77-L113","documentation":"StringLastAggregator computes the latest string value per group; its result is a string (wrapped in SerializablePairLongString), not numeric. getFloat() is unsupported and always throws UnsupportedOperationException. Numeric reads of string-last output are invalid.","triggerScenarios":"Calling getFloat() on StringLastAggregator — e.g. a post-aggregator, finalizer, or generic numeric accessor treating the string-last aggregate as a float.","commonSituations":"FLOAT outputType configured for stringLast; custom post-aggregation over stringLast; shared code calling all numeric getters on aggregator results.","solutions":["Read the value via the aggregator's object/string getter.","Remove numeric outputType or post-aggregators applied to stringLast.","Use FloatLastAggregator (type \"floatLast\") for a numeric latest value.","Verify the aggregator type before numeric access."],"exampleFix":"// before\n{\"type\":\"stringLast\",\"name\":\"s\",\"fieldName\":\"col\",\"outputType\":\"FLOAT\"}\n// after\n{\"type\":\"stringLast\",\"name\":\"s\",\"fieldName\":\"col\"}","handlingStrategy":"type-guard","validationCode":"if (aggregator instanceof StringLastAggregator) {\n  Object v = aggregator.get();\n} else {\n  float v = aggregator.getFloat();\n}","typeGuard":"boolean supportsFloat(Aggregator a) {\n  return !(a instanceof StringLastAggregator);\n}","tryCatchPattern":"try {\n  return agg.getFloat();\n} catch (UnsupportedOperationException e) {\n  Object pair = agg.get();\n  return pair == null ? 0f : Float.parseFloat(String.valueOf(((SerializablePairLongString) pair).rhs));\n}","preventionTips":["Never configure FLOAT outputType on stringLast.","Read string-last results via get().","Use floatLast for numeric latest values."],"tags":["druid","aggregation","unsupported-getter"],"backgroundTag":"unsupported-operation","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}