apache/iceberg · error · UnsupportedOperationException

Cannot specify the 'sort-order' because it's a reserved tabl

Error message

Cannot specify the 'sort-order' because it's a reserved table property. Please use the command 'ALTER TABLE ... WRITE ORDERED BY' to specify write sort-orders.

What it means

ALTER TABLE ... SET TBLPROPERTIES in Spark is intercepted by SparkCatalog.alterTable, which rejects attempts to set reserved Iceberg properties directly. 'sort-order' is managed exclusively through Iceberg's sort-order APIs, exposed in Spark as ALTER TABLE ... WRITE ORDERED BY, so setting it as a property throws UnsupportedOperationException.

Source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:321

  @Override
  public Table alterTable(Identifier ident, TableChange... changes) throws NoSuchTableException {
    SetProperty setLocation = null;
    SetProperty setSnapshotId = null;
    SetProperty pickSnapshotId = null;
    List<TableChange> propertyChanges = Lists.newArrayList();
    List<TableChange> schemaChanges = Lists.newArrayList();

    for (TableChange change : changes) {
      if (change instanceof SetProperty) {
        SetProperty set = (SetProperty) change;
        if (TableCatalog.PROP_LOCATION.equalsIgnoreCase(set.property())) {
          setLocation = set;
        } else if ("current-snapshot-id".equalsIgnoreCase(set.property())) {
          setSnapshotId = set;
        } else if ("cherry-pick-snapshot-id".equalsIgnoreCase(set.property())) {
          pickSnapshotId = set;
        } else if ("sort-order".equalsIgnoreCase(set.property())) {
          throw new UnsupportedOperationException(
              "Cannot specify the 'sort-order' because it's a reserved table "
                  + "property. Please use the command 'ALTER TABLE ... WRITE ORDERED BY' to specify write sort-orders.");
        } else if ("identifier-fields".equalsIgnoreCase(set.property())) {
          throw new UnsupportedOperationException(
              "Cannot specify the 'identifier-fields' because it's a reserved table property. "
                  + "Please use the command 'ALTER TABLE ... SET IDENTIFIER FIELDS' to specify identifier fields.");
        } else {
          propertyChanges.add(set);
        }
      } else if (change instanceof RemoveProperty) {
        propertyChanges.add(change);
      } else if (change instanceof ColumnChange) {
        schemaChanges.add(change);
      } else {
        throw new UnsupportedOperationException("Cannot apply unknown table change: " + change);
      }
    }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Use ALTER TABLE ... WRITE ORDERED BY colA, colB DESC to define the write sort order
  2. Use the Iceberg API: table.replaceSortOrder().asc("col").commit() instead of table properties
  3. Filter out reserved properties ('sort-order', 'identifier-fields', 'current-snapshot-id', etc.) when copying property maps

Example fix

// before
ALTER TABLE t SET TBLPROPERTIES ('sort-order'='id ASC');
// after
ALTER TABLE t WRITE ORDERED BY id ASC;
Defensive patterns

Strategy: validation

Validate before calling

Set<String> reserved = Set.of("sort-order","identifier-fields","current-snapshot-id","cherry-pick-snapshot-id","format-version"); if (reserved.contains(propKey.toLowerCase(Locale.ROOT))) { /* use dedicated SQL/API instead */ }

Type guard

boolean isReservedIcebergProperty(String key) { return RESERVED_KEYS.contains(key.toLowerCase(Locale.ROOT)); }

Try / catch

try { spark.sql("ALTER TABLE t SET TBLPROPERTIES (...)"); } catch (UnsupportedOperationException e) { log.error("Use WRITE ORDERED BY for sort orders"); throw e; }

Prevention

When it happens

Trigger: Running ALTER TABLE ... SET TBLPROPERTIES ('sort-order'='...') (or SparkCatalog.alterTable receiving a SetProperty change with property 'sort-order', case-insensitively).

Common situations: Users porting scripts that set internal Iceberg metadata as table properties; copying properties from one table's properties() output and replaying them into SET TBLPROPERTIES; automating table creation by copying a full property map.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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