apache/iceberg · error · UnsupportedOperationException
does not implement eval(DataFile)
Error message
does not implement eval(DataFile)
What it means
BoundAggregate.eval(DataFile) is a stub that concrete aggregate subclasses must override to compute aggregate values from a data file's metrics. Calling it on a subclass that does not support file-level evaluation throws this UnsupportedOperationException naming the class.
Source
Thrown at api/src/main/java/org/apache/iceberg/expressions/BoundAggregate.java:40
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()");
}
boolean containsNan(DataFile file, int fieldId) {
Long nanCount = safeGet(file.nanValueCounts(), fieldId);
return nanCount != null && nanCount > 0;
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Check the bound aggregate's op() before file-level evaluation and skip unsupported ops
- Use AggregateEvaluator which routes to supported implementations
- Override eval(DataFile) in custom BoundAggregate subclasses
- Fall back to not pruning the file when the aggregate cannot be evaluated
Example fix
// before
Object v = agg.eval(dataFile); // throws for unsupported types
// after
if (agg.op() == Operation.COUNT || agg.op() == Operation.MAX || agg.op() == Operation.MIN) {
Object v = agg.eval(dataFile);
} Defensive patterns
Strategy: try-catch
Validate before calling
boolean supported = Set.of(Operation.COUNT, Operation.MAX, Operation.MIN).contains(agg.op());
Try / catch
try { v = agg.eval(dataFile); } catch (UnsupportedOperationException e) { v = null; /* skip pruning for this file */ } Prevention
- Only evaluate known-supported aggregate ops at file level
- Default to conservative (no-prune) behavior on failure
- Prefer AggregateEvaluator over direct eval calls
When it happens
Trigger: Calling eval(DataFile) on a BoundAggregate subclass that only supports row evaluation (implements eval(StructLike) but not file metrics evaluation).
Common situations: Custom metrics-pruning code evaluating unsupported aggregate types against files; new aggregate operations added in API code without a DataFile implementation.
Related errors
- does not implement eval(StructLike)
- 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/c9d77f9c92529827.
Report an issue: GitHub.