apache/iceberg · error · IllegalArgumentException

Cannot use column %s of type %s in ZOrdering, the type is un

Error message

Cannot use column %s of type %s in ZOrdering, the type is unsupported

What it means

SparkZOrderUDF.sortedLexicographically builds a Spark expression that converts a column's values to lexicographically ordered bytes for Z-Order sorting. It only supports a fixed set of Spark types (numeric, string, binary, date, timestamp, timestamp_ntz, boolean, etc.); anything else reaches the final else branch. This IllegalArgumentException tells you the column's Spark type cannot be Z-ordered by this UDF.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/actions/SparkZOrderUDF.java:343

      return longToOrderedBytesUDF().apply(column);
    } else if (type instanceof FloatType) {
      return floatToOrderedBytesUDF().apply(column);
    } else if (type instanceof DoubleType) {
      return doubleToOrderedBytesUDF().apply(column);
    } else if (type instanceof StringType) {
      return stringToOrderedBytesUDF().apply(column);
    } else if (type instanceof BinaryType) {
      return bytesTruncateUDF().apply(column);
    } else if (type instanceof BooleanType) {
      return booleanToOrderedBytesUDF().apply(column);
    } else if (type instanceof TimestampType) {
      return longToOrderedBytesUDF().apply(column.cast(DataTypes.LongType));
    } else if (type instanceof TimestampNTZType) {
      return timestampNtzToOrderedBytesUDF().apply(column);
    } else if (type instanceof DateType) {
      return longToOrderedBytesUDF().apply(column.cast(DataTypes.LongType));
    } else {
      throw new IllegalArgumentException(
          String.format(
              "Cannot use column %s of type %s in ZOrdering, the type is unsupported",
              column, type));
    }
  }

  private void increaseOutputSize(int bytes) {
    totalOutputBytes = Math.min(totalOutputBytes + bytes, maxOutputSize);
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Choose sort columns with supported primitive types (int/long/double/string/boolean/date/timestamp/timestamp_ntz/binary/decimal).
  2. Extract a supported primitive from the complex column before Z-ordering, e.g. cast or select a struct field via a derived column.
  3. If the type is a reasonable candidate for support, upgrade Iceberg to a newer patch/release where more Spark types are handled.
  4. Fall back to a regular sort (sort strategy with sort_order) for the unsupported column instead of zOrderCols.

Example fix

// before
actions.rewriteDataFiles(table).option("strategy", "zorder").zOrder("nested_struct_col").execute();
// after
// Z-order on a supported primitive extracted from the data instead
actions.rewriteDataFiles(table).option("strategy", "zorder").zOrder("nested_struct_col.id").execute();
Defensive patterns

Strategy: validation

Validate before calling

// Before zOrdering, check each column's Spark type
List<String> unsupported = columns.stream()
    .filter(c -> {
      org.apache.spark.sql.types.DataType t = table.schema().findField(c).asStructField().type();
      return t instanceof MapType || t instanceof ArrayType || t instanceof StructType;
    })
    .collect(Collectors.toList());
if (!unsupported.isEmpty()) throw new IllegalArgumentException("Unsupported ZOrder columns: " + unsupported);

Type guard

private static boolean isZOrderSupported(org.apache.spark.sql.types.DataType t) {
  return t instanceof org.apache.spark.sql.types.NumericType
      || t instanceof org.apache.spark.sql.types.StringType
      || t instanceof org.apache.spark.sql.types.BooleanType
      || t instanceof org.apache.spark.sql.types.DateType
      || t instanceof org.apache.spark.sql.types.TimestampType
      || t instanceof org.apache.spark.sql.types.TimestampNTZType
      || t instanceof org.apache.spark.sql.types.BinaryType;
}

Prevention

When it happens

Trigger: Calling SparkActions.get().zOrderTable(...) (rewrite_data_files with zIndex strategy) on a table whose sort columns include a Spark type with no ordered-bytes UDF, e.g. nested STRUCT, ARRAY, MAP, or an exotic type not covered by the if/else chain in sortedLexicographically.

Common situations: Users pass a struct/map/array column or an unhandled logical type (e.g. interval) to the z-order Columns option; also seen when clustering on columns of newly introduced Spark types that the v3.5 action code does not yet map.

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/30d94fb06f29f576. Report an issue: GitHub.