{"record":{"id":"f405d01f0fbe30d9","repo":"apache/iceberg","slug":"does-not-implement-newaggregator","errorCode":null,"errorMessage":" does not implement newAggregator()","messagePattern":" does not implement newAggregator\\(\\)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/expressions/BoundAggregate.java","lineNumber":50,"sourceCode":"\n  @Override\n  public C eval(StructLike struct) {\n    throw new UnsupportedOperationException(\n        this.getClass().getName() + \" does not implement eval(StructLike)\");\n  }\n\n  C eval(DataFile file) {\n    throw new UnsupportedOperationException(\n        this.getClass().getName() + \" does not implement eval(DataFile)\");\n  }\n\n  boolean hasValue(DataFile file) {\n    throw new UnsupportedOperationException(\n        this.getClass().getName() + \" does not implement hasValue(DataFile)\");\n  }\n\n  Aggregator<C> newAggregator() {\n    throw new UnsupportedOperationException(\n        this.getClass().getName() + \" does not implement newAggregator()\");\n  }\n\n  boolean containsNan(DataFile file, int fieldId) {\n    Long nanCount = safeGet(file.nanValueCounts(), fieldId);\n    return nanCount != null && nanCount > 0;\n  }\n\n  @Override\n  public BoundReference<?> ref() {\n    return term().ref();\n  }\n\n  public Type type() {\n    if (op() == Operation.COUNT || op() == Operation.COUNT_STAR || op() == Operation.COUNT_NULL) {\n      return Types.LongType.get();\n    } else {\n      return term().type();","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/expressions/BoundAggregate.java#L32-L68","documentation":"newAggregator() creates a streaming Aggregator instance for incremental evaluation; the BoundAggregate base class stub always throws UnsupportedOperationException. Subclasses that do not support row/streaming aggregation trigger this error.","triggerScenarios":"Requesting an Aggregator from a BoundAggregate subclass that only supports file-metrics evaluation, e.g. streaming aggregation over rows of an unsupported aggregate type.","commonSituations":"Custom aggregation pipelines that assume every bound aggregate can aggregate rows incrementally; running Expression aggregation paths on aggregates designed only for metrics pruning.","solutions":["Use only COUNT/COUNT_IF/MAX/MIN aggregates with streaming Aggregator paths","Route file-level evaluation through AggregateEvaluator instead","Override newAggregator() in custom BoundAggregate implementations","Check op() before requesting an Aggregator"],"exampleFix":"// before\nAggregator<?> aggregator = agg.newAggregator(); // throws\n// after\nswitch (agg.op()) {\n  case COUNT: case MAX: case MIN: aggregator = agg.newAggregator(); break;\n  default: /* use file-metrics evaluation instead */ break;\n}","handlingStrategy":"type-guard","validationCode":"boolean streamable = Set.of(Operation.COUNT, Operation.MAX, Operation.MIN).contains(agg.op());","typeGuard":"boolean streamable = agg instanceof BoundCount || agg instanceof BoundMax || agg instanceof BoundMin;","tryCatchPattern":"try { aggregator = agg.newAggregator(); } catch (UnsupportedOperationException e) { /* use file-metrics path instead */ }","preventionTips":["Only stream aggregates known to support incremental aggregation","Route metrics evaluation through AggregateEvaluator","Validate aggregate ops at expression-construction time"],"tags":["expressions","aggregates","unsupported-operation"],"backgroundTag":"method-not-implemented","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}