{"record":{"id":"05a4daaf32c408f1","repo":"apache/iceberg","slug":"does-not-implement-eval-structlike","errorCode":null,"errorMessage":" does not implement eval(StructLike)","messagePattern":" does not implement eval\\(StructLike\\)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/expressions/BoundAggregate.java","lineNumber":35,"sourceCode":" * under the License.\n */\npackage org.apache.iceberg.expressions;\n\nimport java.util.Map;\nimport org.apache.iceberg.DataFile;\nimport org.apache.iceberg.StructLike;\nimport org.apache.iceberg.types.Type;\nimport org.apache.iceberg.types.Types;\n\npublic class BoundAggregate<T, C> extends Aggregate<BoundTerm<T>> implements Bound<C> {\n\n  protected BoundAggregate(Operation op, BoundTerm<T> term) {\n    super(op, term);\n  }\n\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","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/expressions/BoundAggregate.java#L17-L53","documentation":"The abstract BoundAggregate.eval(StructLike) has no generic implementation because per-row evaluation is specific to each concrete aggregate type. Subclasses that do not support row-level evaluation inherit this stub, which throws UnsupportedOperationException with the concrete class name.","triggerScenarios":"Calling eval(StructLike) on a BoundCount, BoundMax, or BoundMin subclass instance that only implements eval(DataFile), e.g. evaluating a metrics aggregate against individual rows.","commonSituations":"Custom expression evaluation code that assumes every bound expression supports row evaluation; using aggregate expressions in row-filter pipelines where they were meant for file-level metric pruning.","solutions":["Evaluate aggregates at the data-file level via eval(DataFile) instead of per-row","Only use aggregate expressions with AggregateEvaluator / metrics evaluation APIs","If writing a custom BoundAggregate subclass, override eval(StructLike)","Check the aggregate operation type before attempting row evaluation"],"exampleFix":"// before\nObject value = boundAggregate.eval(rowStruct); // throws\n// after\nObject value = boundAggregate.eval(dataFile); // metrics-level evaluation","handlingStrategy":"type-guard","validationCode":"if (!(agg.op() == Operation.COUNT || agg.op() == Operation.MAX || agg.op() == Operation.MIN)) { /* not row-evaluable */ }","typeGuard":"boolean rowEvaluable = agg instanceof BoundCount || agg instanceof BoundMax || agg instanceof BoundMin;","tryCatchPattern":"try { v = agg.eval(struct); } catch (UnsupportedOperationException e) { /* fall back to file-level eval(DataFile) */ }","preventionTips":["Treat aggregates as file-metrics constructs, not row expressions","Use AggregateEvaluator for aggregate evaluation","Check concrete subclass before per-row eval"],"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"}