{"record":{"id":"a20e5b8e91128b7d","repo":"apache/druid","slug":"stringfirstaggregator-does-not-support-getfloat","errorCode":null,"errorMessage":"StringFirstAggregator does not support getFloat()","messagePattern":"StringFirstAggregator 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/first/StringFirstAggregator.java","lineNumber":95,"sourceCode":"\n      if (time < firstTime) {\n        final String value = DimensionHandlerUtils.convertObjectToString(valueSelector.getObject());\n        firstTime = time;\n        firstValue = StringUtils.fastLooseChop(value, maxStringBytes);\n      }\n    }\n  }\n\n  @Override\n  public Object get()\n  {\n    return new SerializablePairLongString(firstTime, StringUtils.chop(firstValue, maxStringBytes));\n  }\n\n  @Override\n  public float getFloat()\n  {\n    throw new UnsupportedOperationException(\"StringFirstAggregator does not support getFloat()\");\n  }\n\n  @Override\n  public long getLong()\n  {\n    throw new UnsupportedOperationException(\"StringFirstAggregator does not support getLong()\");\n  }\n\n  @Override\n  public double getDouble()\n  {\n    throw new UnsupportedOperationException(\"StringFirstAggregator 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/first/StringFirstAggregator.java#L77-L113","documentation":"StringFirstAggregator computes the earliest string value per group; its result type is a string (wrapped in a SerializablePairLongString), not numeric. getFloat() is therefore unsupported and always throws UnsupportedOperationException. Queries or post-aggregations requesting a float from this aggregator are invalid.","triggerScenarios":"Accessing getFloat() on a StringFirstAggregator result — typically a finalizing/post-aggregation step treating the string-first output as a float, or a factory contract calling numeric getters unconditionally.","commonSituations":"Writing a custom post-aggregator over stringFirst output, using stringFirst with an outputType of float/long, or framework code iterating numeric getters on an aggregator buffer.","solutions":["Do not call getFloat(); use the aggregator's string result via the proper getter/serialized form.","Remove any post-aggregator or outputType that treats stringFirst output as numeric.","Use a numeric-first/last aggregator (e.g. FloatFirst/DoubleFirst) if a numeric earliest value is needed.","Wrap the access with a type check on the aggregator's result type before invoking numeric getters."],"exampleFix":"// before\nAggregatorFactory first = new StringFirstAggregatorFactory(\"f\", \"col\", null, null);\nfloat v = ((BufferAggregator) agg).getFloat(buf, pos);\n// after\nObject v = ((StringFirstBufferAggregator) agg).get(buf, pos); // string pair, not float","handlingStrategy":"type-guard","validationCode":"if (aggregator instanceof StringFirstAggregator) {\n  Object v = aggregator.get(); // string pair\n} else {\n  float v = aggregator.getFloat();\n}","typeGuard":"boolean hasNumericResult(Aggregator a) {\n  return !(a instanceof StringFirstAggregator);\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 numeric outputType on stringFirst.","Read string-first results via get().","Use dedicated numeric first/last aggregators for numbers."],"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-14T05:17:10.506Z"}