apache/iceberg · error · java.lang.UnsupportedOperationException

Cannot convert unknown expression

Error message

Cannot convert unknown expression: <expr>

What it means

toIcebergTerm handles two kinds of Spark expression trees: transforms and NamedReference (plain column references). Anything else at the top level cannot be mapped to an Iceberg Term and throws UnsupportedOperationException with the expression's toString.

Solutions

  1. Use plain column references or supported transforms in the DDL clause
  2. Pre-compute complex expressions into a materialized column, then reference that column
  3. Validate the expression is a Transform or NamedReference before calling toIcebergTerm

Example fix

// before
SORTED BY (upper(name));
// after
SORTED BY (name);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(expr instanceof Transform) && !(expr instanceof NamedReference)) {
  throw new IllegalArgumentException("Only columns and transforms are supported: " + expr);
}

Type guard

static boolean isConvertibleTerm(Expression expr) {
  return expr instanceof Transform || expr instanceof NamedReference;
}

Try / catch

try {
  Term term = Spark3Util.toIcebergTerm(expr);
} catch (UnsupportedOperationException e) {
  // surface a clear DDL error telling users to use plain columns or transforms
}

Prevention

When it happens

Trigger: Passing a complex Spark expression (e.g. a predicate or function call, not a bare column or transform) into Spark3Util.toIcebergTerm.

Common situations: DDL constructs like ORDER/CLUSTER BY with computed expressions rather than plain columns; custom extensions emitting arbitrary expressions where only references/transforms are expected.

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/fd53637d5959abda. Report an issue: GitHub.

Appendix: source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java:421

                  .map(ref -> DOT.join(ref.fieldNames()))
                  .map(org.apache.iceberg.expressions.Expressions::ref)
                  .collect(Collectors.toList()));
        case "hilbert":
          return new Hilbert(
              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)