apache/iceberg · error · UnsupportedOperationException
${className} does not implement countFor(DataFile)
Error message
${className} does not implement countFor(DataFile) What it means
The DataFile overload of CountAggregate.countFor is likewise a stub throwing UnsupportedOperationException. Concrete subclasses must override countFor(DataFile) to compute counts from file metadata. Evaluating the aggregate with a DataFile evaluator on a subclass lacking that override throws this.
Source
Thrown at api/src/main/java/org/apache/iceberg/expressions/CountAggregate.java:45
}
@Override
public Long eval(StructLike struct) {
return countFor(struct);
}
@Override
public Long eval(DataFile file) {
return countFor(file);
}
protected Long countFor(StructLike row) {
throw new UnsupportedOperationException(
this.getClass().getName() + " does not implement countFor(StructLike)");
}
protected Long countFor(DataFile file) {
throw new UnsupportedOperationException(
this.getClass().getName() + " does not implement countFor(DataFile)");
}
@Override
public Aggregator<Long> newAggregator() {
return new CountAggregator<>(this);
}
private static class CountAggregator<T> extends NullSafeAggregator<T, Long> {
private Long count = 0L;
CountAggregator(BoundAggregate<T, Long> aggregate) {
super(aggregate);
}
@Override
protected void update(Long value) {
count += value;View on GitHub (pinned to 86d9c8fc54)
Solutions
- Override countFor(DataFile) in the CountAggregate subclass
- Restrict evaluation to row-based paths if only the StructLike variant exists
- Check the aggregate's supported evaluation mode before choosing the evaluator
Example fix
// before
class MyCount extends CountAggregate<Void> { /* only countFor(StructLike) overridden */ }
// after
class MyCount extends CountAggregate<Void> {
@Override
protected Long countFor(DataFile file) { return file.recordCount(); }
} Defensive patterns
Strategy: validation
Validate before calling
// ensure the subclass implements the DataFile path before scan-planning evaluation
if (!implementsDataFileCount(agg)) { throw new IllegalStateException("subclass must override countFor(DataFile)"); } Type guard
boolean supportsFileEval = !(agg instanceof CountAggregate) || overridesCountForDataFile(agg);
Try / catch
try { return agg.eval(dataFile); } catch (UnsupportedOperationException e) { /* fall back to row-based evaluation or skip metric pushdown */ } Prevention
- Override countFor(DataFile) in CountAggregate subclasses used during scan planning
- Only use file-metric aggregates in file-evaluation contexts
- Test aggregates against both evaluator paths
When it happens
Trigger: Calling eval(DataFile) or countFor(DataFile) on a CountAggregate subclass that only implemented countFor(StructLike).
Common situations: Running aggregate expressions during scan planning (which evaluates against DataFile objects) with an aggregate subclass implemented only for row-level evaluation.
Related errors
- does not implement countFor(StructLike)
- Invalid aggregate:
- does not implement eval(StructLike)
- does not implement eval(DataFile)
- does not implement hasValue(DataFile)
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/48d4bac75b5ac538.
Report an issue: GitHub.