apache/iceberg · error · UnsupportedOperationException
AboveMax has no comparator
Error message
AboveMax has no comparator
What it means
AboveMax is a sentinel literal representing values larger than any representable value of a column's type (e.g. from literal conversion overflow). It exists only so predicate binding can detect 'value too large' and rewrite comparisons (e.g. LT becomes always-false). It carries no actual value, so obtaining a Comparator for it is meaningless and the library throws UnsupportedOperationException.
Source
Thrown at api/src/main/java/org/apache/iceberg/expressions/Literals.java:193
static class AboveMax<T> implements Literal<T> {
private static final AboveMax INSTANCE = new AboveMax();
private AboveMax() {}
@Override
public T value() {
throw new UnsupportedOperationException("AboveMax has no value");
}
@Override
public <X> Literal<X> to(Type type) {
throw new UnsupportedOperationException("Cannot change the type of AboveMax");
}
@Override
public Comparator<T> comparator() {
throw new UnsupportedOperationException("AboveMax has no comparator");
}
@Override
public String toString() {
return "aboveMax";
}
}
static class BelowMin<T> implements Literal<T> {
private static final BelowMin INSTANCE = new BelowMin();
private BelowMin() {}
@Override
public T value() {
throw new UnsupportedOperationException("BelowMin has no value");
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Exclude Literals.aboveMax() and Literals.belowMax() sentinels before calling comparator(); handle them with dedicated comparison logic
- Check the literal class/sentinel identity first and branch to sentinel-aware logic
- Use the bound expression API (Expressions/Binder) instead of manually comparing sentinel literals
Example fix
// before
Comparator<T> cmp = lit.comparator();
// after
if (lit == Literals.aboveMax() || lit == Literals.belowMin()) {
// handle sentinel: comparison result is decided by the operation, not a comparator
} else {
Comparator<T> cmp = lit.comparator();
} Defensive patterns
Strategy: type-guard
Validate before calling
if (lit == Literals.aboveMax() || lit == Literals.belowMin()) { throw new IllegalArgumentException("Sentinel literal has no comparator"); } Type guard
static boolean isSentinel(Literal<?> lit) { return lit == Literals.aboveMax() || lit == Literals.belowMin(); } Try / catch
try { Comparator<?> cmp = lit.comparator(); } catch (UnsupportedOperationException e) { /* sentinel path: resolve via operation semantics */ } Prevention
- Always identity-check Literals.aboveMax()/belowMin() before generic literal operations
- Prefer binding predicates via Binder instead of manual literal comparison
- Unit-test custom visitors against predicates that trigger conversion overflow
When it happens
Trigger: Calling comparator() on the object returned by Literals.aboveMax(), typically after literal().to(type) returned aboveMax during predicate binding, or explicitly calling Literals.aboveMax().comparator() in custom expression code.
Common situations: Custom scan-planning or expression-rewriting code that generically calls literal.comparator() on every literal without excluding the aboveMax/belowMin sentinels.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- BelowMin has no value
- BelowMin has no comparator
- Cannot change the type of BelowMin
- Unsupported aggregate type: %s
- Cannot convert JSON to literal: " + node
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/1fbcf4a72e21af40.
Report an issue: GitHub.