{"record":{"id":"e0dad5cc1b59772a","repo":"apache/druid","slug":"stringfirstaggregator-does-not-support-getfloat-e0dad5","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/StringFirstBufferAggregator.java","lineNumber":115,"sourceCode":"            buf,\n            position,\n            new SerializablePairLongString(time, value),\n            maxStringBytes\n        );\n      }\n    }\n  }\n\n  @Override\n  public Object get(ByteBuffer buf, int position)\n  {\n    return StringFirstLastUtils.readPair(buf, position);\n  }\n\n  @Override\n  public float getFloat(ByteBuffer buf, int position)\n  {\n    throw new UnsupportedOperationException(\"StringFirstAggregator does not support getFloat()\");\n  }\n\n  @Override\n  public long getLong(ByteBuffer buf, int position)\n  {\n    throw new UnsupportedOperationException(\"StringFirstAggregator does not support getLong()\");\n  }\n\n  @Override\n  public double getDouble(ByteBuffer buf, int position)\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":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstBufferAggregator.java#L97-L133","documentation":"StringFirstBufferAggregator buffers the earliest string value per group; the buffered result is a serialized string pair, not numeric. getFloat(ByteBuffer,int) is unsupported and always throws UnsupportedOperationException, indicating the caller used a numeric read on a string aggregate slot.","triggerScenarios":"Calling getFloat(buf, position) on a StringFirstBufferAggregator buffer — typically generic aggregation-result code that reads the group's cell as a float, or a post-aggregator assuming float output.","commonSituations":"Custom aggregation pipelines reading buffer aggregator cells uniformly as numeric; query plans with numeric outputType over stringFirst; framework code paths that iterate numeric getters.","solutions":["Read the buffered value via get(buf, position), which deserializes the string pair.","Remove numeric outputType/post-aggregations on stringFirst.","Use FloatFirst aggregator for numeric earliest values.","Type-check the aggregator before calling numeric buffer getters."],"exampleFix":"// before\nfloat v = bufAggregator.getFloat(buf, pos);\n// after\nObject v = bufAggregator.get(buf, pos); // SerializablePairLongString","handlingStrategy":"type-guard","validationCode":"if (bufAggregator instanceof StringFirstBufferAggregator) {\n  Object v = bufAggregator.get(buf, position);\n} else {\n  float v = bufAggregator.getFloat(buf, position);\n}","typeGuard":"boolean supportsFloat(BufferAggregator a) {\n  return !(a instanceof StringFirstBufferAggregator);\n}","tryCatchPattern":"try {\n  return agg.getFloat(buf, pos);\n} catch (UnsupportedOperationException e) {\n  Object pair = agg.get(buf, pos);\n  return pair == null ? 0f : Float.parseFloat(String.valueOf(((SerializablePairLongString) pair).rhs));\n}","preventionTips":["Route string-first buffer cells through get().","Keep outputType consistent with the aggregator type.","Dispatch numeric reads based on aggregator class."],"tags":["druid","aggregation","buffer-aggregator","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"}