apache/iceberg · error · UnsupportedOperationException

does not implement hasValue(DataFile)

Error message

 does not implement hasValue(DataFile)

What it means

hasValue(DataFile) indicates whether a data file's metrics contain a value the aggregate can use; the base BoundAggregate stub always throws. Subclasses not supporting file-level metrics evaluation trigger this UnsupportedOperationException.

Source

Thrown at api/src/main/java/org/apache/iceberg/expressions/BoundAggregate.java:45

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;
  }

  @Override
  public BoundReference<?> ref() {
    return term().ref();
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Guard with try-catch or check op() type before calling hasValue
  2. Use AggregateEvaluator's supported aggregates for file pruning
  3. Override hasValue(DataFile) in custom subclasses
  4. Default to assuming a value exists (no pruning) when unsupported

Example fix

// before
boolean has = agg.hasValue(dataFile); // throws
// after
boolean has = agg.op() == Operation.COUNT || agg.evalHasValue(dataFile); // route via supported path
Defensive patterns

Strategy: try-catch

Validate before calling

boolean supported = Set.of(Operation.COUNT, Operation.MAX, Operation.MIN).contains(agg.op());

Try / catch

try { has = agg.hasValue(dataFile); } catch (UnsupportedOperationException e) { has = true; /* assume value present, skip pruning */ }

Prevention

When it happens

Trigger: Calling hasValue(DataFile) on a BoundAggregate subclass lacking file-metrics support, typically during file pruning with aggregate pushdown.

Common situations: Custom pruning implementations probing metrics for aggregate types that do not support them; API evolution where new aggregates lag behind file-level support.

Related errors


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