apache/iceberg · error · UnsupportedOperationException
Cannot convert predicate to SQL:
Error message
Cannot convert predicate to SQL:
What it means
The unbound predicate branch of DescribeExpressionVisitor renders Iceberg predicates as SQL strings for DESCRIBE output. It supports is-null/not-null, eq/neq/lt/lteq/gt/gteq, starts-with/not-starts-with, in/not-in; other operators (e.g. not, count*, equality on terms it can't render) fall to default and throw UnsupportedOperationException.
Solutions
- Rewrite the filter using supported operators (e.g. replace NOT(x) with its negated comparison)
- Handle unsupported operators in your own rendering instead of DescribeExpressionVisitor
- Upgrade Iceberg Spark module if the operator should be supported in newer versions
Example fix
// before
Expressions.not(Expressions.equal("a", 1)) // hits unsupported default in some paths
// after
Expressions.notEqual("a", 1) Defensive patterns
Strategy: try-catch
Validate before calling
Set<Expression.Operation> supported = Set.of(IS_NULL, NOT_NULL, EQ, NOT_EQ, LT, LT_EQ,
GT, GT_EQ, STARTS_WITH, NOT_STARTS_WITH, IN, NOT_IN);
if (!supported.contains(pred.op())) throw new IllegalArgumentException("Unsupported op: " + pred.op()); Type guard
boolean isRenderablePredicate(UnboundPredicate<?> p) {
return switch (p.op()) {
case IS_NULL, NOT_NULL, EQ, NOT_EQ, LT, LT_EQ, GT, GT_EQ,
STARTS_WITH, NOT_STARTS_WITH, IN, NOT_IN -> true;
default -> false;
};
} Try / catch
try {
String sql = visitor.predicate(pred);
} catch (UnsupportedOperationException e) {
return pred.toString(); // fall back to Iceberg expression string
} Prevention
- Compose filters from supported comparison/set operators only
- Avoid NOT-wrapped predicates when rendering through the describe visitor
- Version-match the connector with the expression spec in use
When it happens
Trigger: DESCRIBE/EXPLAIN-style SQL rendering of an Iceberg predicate using an operator outside the supported switch, such as predicates containing NOT wrappers reaching this path or new operator types added in later Iceberg specs.
Common situations: Rendering filters with less-common operators through Spark3Util's describe helpers; schema evolution or version skew where newer predicates are passed to an older converter.
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 convert term to SQL:
- Cannot parse predicates in where option:
- Cannot parse predicates in where option:
- Cannot parse predicates in where option
- Already closed files for partition:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/fcad2a45c37ffca0.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java:686
return sqlString(pred.term()) + " <= " + sqlString(pred.literal());
case GT:
return sqlString(pred.term()) + " > " + sqlString(pred.literal());
case GT_EQ:
return sqlString(pred.term()) + " >= " + sqlString(pred.literal());
case EQ:
return sqlString(pred.term()) + " = " + sqlString(pred.literal());
case NOT_EQ:
return sqlString(pred.term()) + " != " + sqlString(pred.literal());
case STARTS_WITH:
return sqlString(pred.term()) + " LIKE '" + pred.literal().value() + "%'";
case NOT_STARTS_WITH:
return sqlString(pred.term()) + " NOT LIKE '" + pred.literal().value() + "%'";
case IN:
return sqlString(pred.term()) + " IN (" + sqlString(pred.literals()) + ")";
case NOT_IN:
return sqlString(pred.term()) + " NOT IN (" + sqlString(pred.literals()) + ")";
default:
throw new UnsupportedOperationException("Cannot convert predicate to SQL: " + pred);
}
}
private static <T> String sqlString(UnboundTerm<T> term) {
if (term instanceof org.apache.iceberg.expressions.NamedReference) {
return term.ref().name();
} else if (term instanceof UnboundTransform) {
UnboundTransform<?, ?> transform = (UnboundTransform<?, ?>) term;
return transform.transform().toString() + "(" + transform.ref().name() + ")";
} else {
throw new UnsupportedOperationException("Cannot convert term to SQL: " + term);
}
}
private static <T> String sqlString(List<org.apache.iceberg.expressions.Literal<T>> literals) {
return literals.stream()
.map(DescribeExpressionVisitor::sqlString)
.collect(Collectors.joining(", "));View on GitHub (pinned to 86d9c8fc54)