apache/iceberg · error · UnsupportedOperationException
Cannot sanitize bound predicate type
Error message
Cannot sanitize bound predicate type: ${operation} What it means
The bound-predicate sanitizer in ExpressionUtil only supports bound predicates whose operation takes literals (eq, lt, in, etc.). Operations without bound literal representation (e.g. startsWith on some paths, or count/null ops reached here unexpectedly) fall through to this UnsupportedOperationException.
Solutions
- Upgrade Iceberg — newer versions extend the sanitizer to more bound operations
- Sanitize the expression before binding (use the unbound predicate sanitizer path) instead of after
- Pre-check pred.op() and skip/handle unsupported operations before sanitizing
- If sanitizing for logging, fall back to describing the predicate without value redaction for unsupported ops
Example fix
// before
Expression safe = ExpressionUtil.sanitize(boundStartsWithPredicate, now, today);
// after
Expression safe = pred.op() == Expression.Operation.STARTS_WITH
? pred // handle or skip unsupported op
: ExpressionUtil.sanitize(pred, now, today); Defensive patterns
Strategy: try-catch
Validate before calling
Expression.Operation op = pred.op();
if (op == Expression.Operation.STARTS_WITH || op == Expression.Operation.NOT_STARTS_WITH) {
throw new IllegalArgumentException("sanitize() does not support bound op: " + op);
} Try / catch
try { return ExpressionUtil.sanitize(expr, now, today); }
catch (UnsupportedOperationException e) { return expr; /* unsanitized fallback */ } Prevention
- Pre-check Expression.Operation against supported sanitizer ops
- Sanitize before binding when possible
- Upgrade Iceberg when using newer predicate operations
When it happens
Trigger: Running ExpressionUtil.sanitize over a bound predicate whose ExpressionOperation is not one the sanitizer switch handles (e.g. STARTS_WITH/NOT_STARTS_WITH or other unhandled bound ops in that visitor).
Common situations: Sanitizing query strings for logging while using string predicates (startsWith) that the bound sanitizer branch does not cover; version drift where new operations were added but the sanitizer was not updated.
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
- Cannot sanitize unsupported predicate type
- AboveMax has no comparator
- BelowMin has no comparator
- BelowMin has no value
- Cannot change the type of BelowMin
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/00ad533b6926639c.
Report an issue: GitHub.
Appendix: source
Thrown at api/src/main/java/org/apache/iceberg/expressions/ExpressionUtil.java:385
public <T> Expression predicate(BoundPredicate<T> pred) {
if (pred.isUnaryPredicate()) {
// unary predicates don't need to be sanitized
return new UnboundPredicate<>(pred.op(), unbind(pred.term()));
} else if (pred.isLiteralPredicate()) {
BoundLiteralPredicate<T> bound = (BoundLiteralPredicate<T>) pred;
return new UnboundPredicate<>(
pred.op(), unbind(pred.term()), (T) sanitize(bound.literal(), now, today));
} else if (pred.isSetPredicate()) {
BoundSetPredicate<T> bound = (BoundSetPredicate<T>) pred;
Iterable<T> iter =
() ->
bound.literalSet().stream()
.map(lit -> (T) sanitize((Literal<?>) lit, now, today))
.iterator();
return new UnboundPredicate<>(pred.op(), unbind(pred.term()), iter);
}
throw new UnsupportedOperationException("Cannot sanitize bound predicate type: " + pred.op());
}
@Override
@SuppressWarnings("unchecked")
public <T> Expression predicate(UnboundPredicate<T> pred) {
switch (pred.op()) {
case IS_NULL:
case NOT_NULL:
case IS_NAN:
case NOT_NAN:
// unary predicates don't need to be sanitized
return pred;
case LT:
case LT_EQ:
case GT:
case GT_EQ:
case EQ:
case NOT_EQ:View on GitHub (pinned to 86d9c8fc54)