apache/iceberg · error · UnsupportedOperationException
does not implement countFor(StructLike)
Error message
does not implement countFor(StructLike)
What it means
CountAggregate is an abstract aggregate evaluated either over StructLike rows or DataFile metadata. The StructLike overload countFor(StructLike) is a stub that throws UnsupportedOperationException; concrete subclasses must override it. Calling eval()/countFor with a row-based context on a subclass that only implemented the DataFile variant hits this.
Source
Thrown at api/src/main/java/org/apache/iceberg/expressions/CountAggregate.java:40
import org.apache.iceberg.StructLike;
public class CountAggregate<T> extends BoundAggregate<T, Long> {
protected CountAggregate(Operation op, BoundTerm<T> term) {
super(op, term);
}
@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);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Override countFor(StructLike) in your CountAggregate subclass
- Use the eval/countFor(DataFile) path if the aggregate is only defined over file metadata
- Verify which evaluator (row-based vs file-based) is being used before evaluating
Example fix
// before
class MyCount extends CountAggregate<Void> { /* only countFor(DataFile) overridden */ }
// after
class MyCount extends CountAggregate<Void> {
@Override
protected Long countFor(StructLike row) { return myRowBasedCount(row); }
} Defensive patterns
Strategy: validation
Validate before calling
if (agg.getClass().equals(CountAggregate.class)) { throw new IllegalStateException("subclass must override countFor(StructLike)"); } Type guard
boolean supportsRowEval = !(agg instanceof CountAggregate) || overridesCountForStructLike(agg);
Try / catch
try { return agg.eval(row); } catch (UnsupportedOperationException e) { /* fall back to DataFile-based evaluation */ } Prevention
- Override countFor(StructLike) in every CountAggregate subclass
- Match aggregate implementation to the evaluation context (rows vs DataFile)
- Document which evaluation modes each custom aggregate supports
When it happens
Trigger: Calling eval(StructLike) or countFor(StructLike) on a CountAggregate subclass (e.g. one written for DataFile metrics) that has not overridden countFor(StructLike).
Common situations: Evaluating aggregate expressions (e.g. row-count aggregates) against data rows when the aggregate was implemented for file metadata evaluation, or using a custom aggregate in a context that supplies StructLike input.
Related errors
- ${className} does not implement countFor(DataFile)
- 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/dece6502c588bb95.
Report an issue: GitHub.