apache/iceberg · error · UnsupportedOperationException

BelowMin has no comparator

Error message

BelowMin has no comparator

What it means

Same rationale as AboveMax: the BelowMin sentinel carries no value, so no Comparator can be produced for it. Ordering of the sentinel is defined implicitly by predicate-binding semantics (anything is greater than belowMin), not by a comparator object.

Source

Thrown at api/src/main/java/org/apache/iceberg/expressions/Literals.java:219

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

    @Override
    public <X> Literal<X> to(Type type) {
      throw new UnsupportedOperationException("Cannot change the type of BelowMin");
    }

    @Override
    public Comparator<T> comparator() {
      throw new UnsupportedOperationException("BelowMin has no comparator");
    }

    @Override
    public String toString() {
      return "belowMin";
    }
  }

  static class BooleanLiteral extends ComparableLiteral<Boolean> {
    BooleanLiteral(Boolean value) {
      super(value);
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> Literal<T> to(Type type) {
      if (type.typeId() == Type.TypeID.BOOLEAN) {
        return (Literal<T>) this;

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Exclude belowMin/aboveMax sentinels before requesting a comparator and resolve comparisons via operation semantics
  2. Inspect the predicate after binding; bound predicates from sentinels are typically rewritten to always-true/false
  3. Validate literal ranges against the column type up front so sentinels are never produced

Example fix

// before
Comparator<T> cmp = lit.comparator();
// after
if (lit == Literals.belowMin()) {
  // belowMin compares less than everything; no comparator needed
} else {
  Comparator<T> cmp = lit.comparator();
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (lit == Literals.belowMin() || lit == Literals.aboveMax()) { throw new IllegalArgumentException("Sentinel literal has no comparator"); }

Type guard

static boolean hasComparator(Literal<?> lit) { return lit != Literals.belowMin() && lit != Literals.aboveMax(); }

Try / catch

try { Comparator<?> cmp = lit.comparator(); } catch (UnsupportedOperationException e) { /* belowMin is less than everything; decide via operation */ }

Prevention

When it happens

Trigger: Calling comparator() on Literals.belowMin(), e.g. in generic expression evaluation code that obtains a comparator for every literal or bound term.

Common situations: Custom predicate evaluators or metrics-based filter pushdown that uniformly request comparators and trip over sentinel literals produced by conversion overflow/underflow.

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


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