{"record":{"id":"231b560cd5a36ba7","repo":"apache/iceberg","slug":"cannot-convert-unknown-expression-expr","errorCode":null,"errorMessage":"Cannot convert unknown expression: ${expr}","messagePattern":"Cannot convert unknown expression: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java","lineNumber":412,"sourceCode":"          return org.apache.iceberg.expressions.Expressions.hour(colName);\n        case \"truncate\":\n          return org.apache.iceberg.expressions.Expressions.truncate(colName, findWidth(transform));\n        case \"zorder\":\n          return new Zorder(\n              Stream.of(transform.references())\n                  .map(ref -> DOT.join(ref.fieldNames()))\n                  .map(org.apache.iceberg.expressions.Expressions::ref)\n                  .collect(Collectors.toList()));\n        default:\n          throw new UnsupportedOperationException(\"Transform is not supported: \" + transform);\n      }\n\n    } else if (expr instanceof NamedReference) {\n      NamedReference ref = (NamedReference) expr;\n      return org.apache.iceberg.expressions.Expressions.ref(DOT.join(ref.fieldNames()));\n\n    } else {\n      throw new UnsupportedOperationException(\"Cannot convert unknown expression: \" + expr);\n    }\n  }\n\n  /**\n   * Converts Spark transforms into a {@link PartitionSpec}.\n   *\n   * @param schema the table schema\n   * @param partitioning Spark Transforms\n   * @return a PartitionSpec\n   */\n  public static PartitionSpec toPartitionSpec(Schema schema, Transform[] partitioning) {\n    if (partitioning == null || partitioning.length == 0) {\n      return PartitionSpec.unpartitioned();\n    }\n\n    PartitionSpec.Builder builder = PartitionSpec.builderFor(schema);\n    for (Transform transform : partitioning) {\n      Preconditions.checkArgument(","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java#L394-L430","documentation":"toIcebergTerm only understands Transform and NamedReference Spark expressions. Any other expression tree node passed in (e.g. a literal, binary comparison, or function call) cannot be converted to an Iceberg term, so this UnsupportedOperationException is thrown.","triggerScenarios":"Passing a non-transform, non-column expression into partition/sort conversion paths — e.g. IcebergPartitioningHelpers or CREATE TABLE ... PARTITIONED BY with a predicate or computed expression rather than a plain column or supported transform.","commonSituations":"PARTITIONED BY clauses containing arithmetic or function calls (PARTITIONED BY (year(col) + 1)); programmatic construction of V2 expressions that aren't NamedReference/Transform.","solutions":["Use only plain columns or supported transforms in PARTITIONED BY / sort clauses","Add a computed column first, then partition on it","Construct the term programmatically with Expressions.ref/bucket/truncate instead of going through the Spark converter"],"exampleFix":"// before\nPARTITIONED BY (bucket(16, id), ts + INTERVAL 1 DAY)\n// after\nPARTITIONED BY (bucket(16, id), days(ts))","handlingStrategy":"type-guard","validationCode":"if (!(expr instanceof Transform) && !(expr instanceof NamedReference)) { throw new IllegalArgumentException(\"Expression must be a Transform or NamedReference\"); }","typeGuard":"boolean convertibleToIcebergTerm(Expression e) { return e instanceof Transform || e instanceof NamedReference; }","tryCatchPattern":"try { Spark3Util.toIcebergTerm(expr); } catch (UnsupportedOperationException e) { if (e.getMessage().contains(\"Cannot convert unknown expression\")) { /* rebuild the expression as a transform/ref */ } else throw e; }","preventionTips":["Use only column names or supported transforms in PARTITIONED BY clauses","Compute derived values into real columns instead of inlining expressions","When building V2 expressions programmatically, verify the node type before converting"],"tags":["spark","expression","unsupported"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}