apache/iceberg · error · UnsupportedOperationException
Cannot convert unknown expression:
Error message
Cannot convert unknown expression:
What it means
Spark3Util.toIcebergTerm converts Spark V2 expression trees (org.apache.spark.sql.connector.expressions.Expression) into Iceberg expressions. It handles Literal, And, Or, Not, NullsOrdering/options and NamedReference; anything else is untranslatable, so it throws UnsupportedOperationException. This guards DESCRIBE TABLE / partition-spec conversion paths from silently producing wrong filters.
Source
Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java:416
return org.apache.iceberg.expressions.Expressions.hour(colName);
case "truncate":
return org.apache.iceberg.expressions.Expressions.truncate(colName, findWidth(transform));
case "zorder":
return new Zorder(
Stream.of(transform.references())
.map(ref -> DOT.join(ref.fieldNames()))
.map(org.apache.iceberg.expressions.Expressions::ref)
.collect(Collectors.toList()));
default:
throw new UnsupportedOperationException("Transform is not supported: " + transform);
}
} else if (expr instanceof NamedReference) {
NamedReference ref = (NamedReference) expr;
return org.apache.iceberg.expressions.Expressions.ref(DOT.join(ref.fieldNames()));
} else {
throw new UnsupportedOperationException("Cannot convert unknown expression: " + expr);
}
}
/**
* Converts Spark transforms into a {@link PartitionSpec}.
*
* @param schema the table schema
* @param partitioning Spark Transforms
* @return a PartitionSpec
*/
public static PartitionSpec toPartitionSpec(Schema schema, Transform[] partitioning) {
if (partitioning == null || partitioning.length == 0) {
return PartitionSpec.unpartitioned();
}
PartitionSpec.Builder builder = PartitionSpec.builderFor(schema);
for (Transform transform : partitioning) {
Preconditions.checkArgument(View on GitHub (pinned to 86d9c8fc54)
Solutions
- Inspect the failing expression printed in the message; rewrite the query/DDL to use only simple column references, literals and AND/OR/NOT predicates supported by Iceberg
- Check whether the expression is a transform/sort-order that should go through Spark3Util.toIcebergTerm's transform path or V2Expressions, not the predicate path
- Upgrade or patch Iceberg's Spark module to a version that supports this expression type
- If authoring the caller, wrap toIcebergTerm in try/catch for UnsupportedOperationException and degrade to non-pushed filter
Example fix
// before
Expression term = Spark3Util.toIcebergTerm(sparkExpr); // throws on Cast/SortOrder
// after
Expression term;
try {
term = Spark3Util.toIcebergTerm(sparkExpr);
} catch (UnsupportedOperationException e) {
term = Expressions.alwaysTrue(); // fall back: evaluate filter in Spark
} Defensive patterns
Strategy: try-catch
Validate before calling
// Check the expression is one of the supported shapes
boolean supported = expr instanceof Literal || expr instanceof And || expr instanceof Or
|| expr instanceof Not || expr instanceof NamedReference;
if (!supported) throw new IllegalArgumentException("Unsupported Spark expression: " + expr); Type guard
boolean isConvertible(org.apache.spark.sql.connector.expressions.Expression e) {
return e instanceof Literal || e instanceof And || e instanceof Or
|| e instanceof Not || e instanceof NamedReference;
} Try / catch
try {
Expression term = Spark3Util.toIcebergTerm(expr);
} catch (UnsupportedOperationException e) {
LOG.warn("Falling back to Spark-side filtering: {}", e.getMessage());
// keep predicate un-pushed
} Prevention
- Only pass literal/AND/OR/NOT/column-reference expressions to toIcebergTerm
- Keep Spark and Iceberg connector versions aligned
- Guard new expression sources with an instanceof check before conversion
When it happens
Trigger: Calling toIcebergTerm with a Spark expression not in the supported set, e.g. a SortOrder, Cast, UserDefinedExpression, or other NamedExpression/transform produced by Spark's connector API instead of a simple literal/comparison/column reference.
Common situations: Running DESCRIBE TABLE EXTENDED or converting a Spark filter/pushdown on a table whose partition transforms or expressions include constructs Iceberg's Spark conversion doesn't support; typically after Spark version changes or custom catalogs supplying exotic expressions.
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 apply unknown table change: ${change}
- SparkCachedTableCatalog does not support altering tables
- SparkCachedTableCatalog does not support dropping tables
- SparkCachedTableCatalog does not support purging tables
- SparkCachedTableCatalog does not support renaming tables
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/6bdd56f12674e265.
Report an issue: GitHub.