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

  1. Check the bound aggregate's op() before file-level evaluation and skip unsupported ops
  2. Use AggregateEvaluator which routes to supported implementations
  3. Override eval(DataFile) in custom BoundAggregate subclasses
  4. 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

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/c9d77f9c92529827. Report an issue: GitHub.