apache/iceberg · error · java.lang.UnsupportedOperationException
Cannot convert predicate to SQL: %s
Error message
Cannot convert predicate to SQL: %s
What it means
The unbound-predicate branch of DescribeExpressionVisitor throws when the predicate's operator is not one of the explicitly rendered SQL operators (IS_NULL, NOT_NULL, EQ, LT, LTE, GT, GTE, STARTS_WITH, NOT_STARTS_WITH, LIKE, NOT_LIKE, IN, NOT_IN).
Source
Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java:682
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)
Solutions
- Pre-filter or transform the expression to only supported operators before calling describe
- Wrap the call in try/catch for UnsupportedOperationException and fall back to expression.toString()
- Upgrade Iceberg — newer versions add more operator cases (e.g. STARTS_WITH was added over time)
Example fix
// before
String sql = Spark3Util.describe(Expressions.contains("col", "x")); // throws
// after
String sql;
try { sql = Spark3Util.describe(expr); }
catch (UnsupportedOperationException e) { sql = expr.toString(); } Defensive patterns
Strategy: try-catch
Validate before calling
Set<Predicate.Op> SUPPORTED = Set.of(IS_NULL, NOT_NULL, EQ, LT, LTE, GT, GTE, IN, NOT_IN, LIKE, NOT_LIKE); // check pred.op() before describing
Type guard
boolean isSqlRenderableOp(Predicate p) { return SUPPORTED_OPS.contains(p.op()); } Try / catch
try { return Spark3Util.describe(pred); } catch (UnsupportedOperationException e) { return pred.toString(); } Prevention
- Restrict user-facing filters to operators with SQL equivalents
- Fall back to Expression.toString for unsupported operators
- Upgrade Iceberg to pick up newly supported operator cases
When it happens
Trigger: Calling Spark3Util.describe with an unbound predicate whose op() is unsupported, e.g. Expressions.startsWith variants not covered in older versions, COUNT/aggregate predicates, or custom predicate ops.
Common situations: Rendering user filters that use operators without direct SQL equivalents (e.g. 'str.contains' composed as predicate variants, nan/not-nan checks) for SHOW CREATE TABLE or EXPLAIN-style output.
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 bound predicates to SQL
- Cannot convert term to SQL: %s
- Cannot convert type to SQL: %s
- Unsupported format in USING:
- Cannot convert bound predicates to SQL
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/644c7ad6fe344e8f.
Report an issue: GitHub.