apache/iceberg · error · UnsupportedOperationException
does not implement eval(StructLike)
Error message
does not implement eval(StructLike)
What it means
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.
Source
Thrown at api/src/main/java/org/apache/iceberg/expressions/BoundAggregate.java:35
* under the License.
*/
package org.apache.iceberg.expressions;
import java.util.Map;
import org.apache.iceberg.DataFile;
import org.apache.iceberg.StructLike;
import org.apache.iceberg.types.Type;
import org.apache.iceberg.types.Types;
public class BoundAggregate<T, C> extends Aggregate<BoundTerm<T>> implements Bound<C> {
protected BoundAggregate(Operation op, BoundTerm<T> term) {
super(op, term);
}
@Override
public C eval(StructLike struct) {
throw new UnsupportedOperationException(
this.getClass().getName() + " does not implement eval(StructLike)");
}
C eval(DataFile file) {
throw new UnsupportedOperationException(
this.getClass().getName() + " does not implement eval(DataFile)");
}
boolean hasValue(DataFile file) {
throw new UnsupportedOperationException(
this.getClass().getName() + " does not implement hasValue(DataFile)");
}
Aggregator<C> newAggregator() {
throw new UnsupportedOperationException(
this.getClass().getName() + " does not implement newAggregator()");
}
View on GitHub (pinned to 86d9c8fc54)
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
Example fix
// before Object value = boundAggregate.eval(rowStruct); // throws // after Object value = boundAggregate.eval(dataFile); // metrics-level evaluation
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(agg.op() == Operation.COUNT || agg.op() == Operation.MAX || agg.op() == Operation.MIN)) { /* not row-evaluable */ } Type guard
boolean rowEvaluable = agg instanceof BoundCount || agg instanceof BoundMax || agg instanceof BoundMin;
Try / catch
try { v = agg.eval(struct); } catch (UnsupportedOperationException e) { /* fall back to file-level eval(DataFile) */ } Prevention
- Treat aggregates as file-metrics constructs, not row expressions
- Use AggregateEvaluator for aggregate evaluation
- Check concrete subclass before per-row eval
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- does not implement eval(DataFile)
- does not implement hasValue(DataFile)
- does not implement newAggregator()
- Invalid aggregate:
- Found already bound aggregate:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/05a4daaf32c408f1.
Report an issue: GitHub.