{"record":{"id":"2c4493448e7374af","repo":"apache/iceberg","slug":"cannot-specify-the-sort-order-because-it-s-a-res-2c4493","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java","lineNumber":321,"sourceCode":"  @Override\n  public Table alterTable(Identifier ident, TableChange... changes) throws NoSuchTableException {\n    SetProperty setLocation = null;\n    SetProperty setSnapshotId = null;\n    SetProperty pickSnapshotId = null;\n    List<TableChange> propertyChanges = Lists.newArrayList();\n    List<TableChange> schemaChanges = Lists.newArrayList();\n\n    for (TableChange change : changes) {\n      if (change instanceof SetProperty) {\n        SetProperty set = (SetProperty) change;\n        if (TableCatalog.PROP_LOCATION.equalsIgnoreCase(set.property())) {\n          setLocation = set;\n        } else if (\"current-snapshot-id\".equalsIgnoreCase(set.property())) {\n          setSnapshotId = set;\n        } else if (\"cherry-pick-snapshot-id\".equalsIgnoreCase(set.property())) {\n          pickSnapshotId = set;\n        } else if (\"sort-order\".equalsIgnoreCase(set.property())) {\n          throw new UnsupportedOperationException(\n              \"Cannot specify the 'sort-order' because it's a reserved table \"\n                  + \"property. Please use the command 'ALTER TABLE ... WRITE ORDERED BY' to specify write sort-orders.\");\n        } else if (\"identifier-fields\".equalsIgnoreCase(set.property())) {\n          throw new UnsupportedOperationException(\n              \"Cannot specify the 'identifier-fields' because it's a reserved table property. \"\n                  + \"Please use the command 'ALTER TABLE ... SET IDENTIFIER FIELDS' to specify identifier fields.\");\n        } else {\n          propertyChanges.add(set);\n        }\n      } else if (change instanceof RemoveProperty) {\n        propertyChanges.add(change);\n      } else if (change instanceof ColumnChange) {\n        schemaChanges.add(change);\n      } else {\n        throw new UnsupportedOperationException(\"Cannot apply unknown table change: \" + change);\n      }\n    }\n","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java#L303-L339","documentation":"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.","triggerScenarios":"Running ALTER TABLE ... SET TBLPROPERTIES ('sort-order'='...') (or SparkCatalog.alterTable receiving a SetProperty change with property 'sort-order', case-insensitively).","commonSituations":"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.","solutions":["Use ALTER TABLE ... WRITE ORDERED BY colA, colB DESC to define the write sort order","Use the Iceberg API: table.replaceSortOrder().asc(\"col\").commit() instead of table properties","Filter out reserved properties ('sort-order', 'identifier-fields', 'current-snapshot-id', etc.) when copying property maps"],"exampleFix":"// before\nALTER TABLE t SET TBLPROPERTIES ('sort-order'='id ASC');\n// after\nALTER TABLE t WRITE ORDERED BY id ASC;","handlingStrategy":"validation","validationCode":"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 */ }","typeGuard":"boolean isReservedIcebergProperty(String key) { return RESERVED_KEYS.contains(key.toLowerCase(Locale.ROOT)); }","tryCatchPattern":"try { spark.sql(\"ALTER TABLE t SET TBLPROPERTIES (...)\"); } catch (UnsupportedOperationException e) { log.error(\"Use WRITE ORDERED BY for sort orders\"); throw e; }","preventionTips":["Never replay a table's full properties() map into SET TBLPROPERTIES","Filter reserved keys when copying table configuration","Use WRITE ORDERED BY / sortOrder API for sort orders"],"tags":["spark","reserved-property","sort-order"],"backgroundTag":"invalid-argument-value","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"}