apache/iceberg · error · UnsupportedOperationException
Cannot change the type of BelowMin
Error message
Cannot change the type of BelowMin
What it means
Literal.to(Type) converts a literal to another type; for the BelowMin sentinel there is no value to convert, and its meaning (smaller than everything) is type-independent, so conversion is not defined and throws UnsupportedOperationException. This guards against silently treating the sentinel as a real value.
Source
Thrown at api/src/main/java/org/apache/iceberg/expressions/Literals.java:214
@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");
}
@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);
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Short-circuit: if the literal is Literals.belowMin() (or aboveMax()), skip conversion and let predicate-binding semantics handle it
- Validate user-supplied values against the column type before creating a Literal
- Rely on UnboundPredicate.bind, which detects sentinels and rewrites operations rather than converting them
Example fix
// before
Literal<?> converted = lit.to(targetType);
// after
if (lit == Literals.belowMin() || lit == Literals.aboveMax()) {
// handle sentinel at the predicate level; do not convert
} else {
Literal<?> converted = lit.to(targetType);
} Defensive patterns
Strategy: type-guard
Validate before calling
Preconditions.checkState(lit != Literals.belowMin() && lit != Literals.aboveMax(), "Cannot convert sentinel literal");
Type guard
static boolean isConvertible(Literal<?> lit) { return lit != Literals.belowMin() && lit != Literals.aboveMax(); } Try / catch
try { Literal<?> c = lit.to(target); } catch (UnsupportedOperationException e) { /* skip conversion; handle sentinel */ } Prevention
- Skip conversion for sentinel literals in expression visitors
- Validate literal type compatibility before calling to()
- Use UnboundPredicate.bind rather than manual conversions
When it happens
Trigger: Calling to(...) on Literals.belowMin(), typically in generic literal-conversion code, or re-converting a literal that already underflowed during binding.
Common situations: Custom expression visitors that call literal.to(targetType) on every literal in a predicate, hitting the sentinel produced by a previous failed conversion.
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
- AboveMax has no comparator
- BelowMin has no value
- BelowMin has no comparator
- Cannot change the type of AboveMax
- Invalid value for conversion to type %s: %s (%s)
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/b43e1c2f01695f85.
Report an issue: GitHub.