{"record":{"id":"619d47054698bc08","repo":"apache/iceberg","slug":"cannot-specify-the-sort-order-because-it-s-a-res-619d47","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":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java","lineNumber":293,"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":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java#L275-L311","documentation":"'sort-order' is a reserved Iceberg table property managed through dedicated DDL, not a settable property. alterTable explicitly rejects SET TBLPROPERTIES attempts to change it with this UnsupportedOperationException, directing users to ALTER TABLE ... WRITE ORDERED BY.","triggerScenarios":"ALTER TABLE ... SET TBLPROPERTIES ('sort-order'='...') on an Iceberg table via SparkCatalog.alterTable.","commonSituations":"Scripts copied from older Iceberg versions where sort orders were manipulated via properties; users mistaking sort-order for a normal tunable property; migration scripts writing reserved keys blindly.","solutions":["Use ALTER TABLE ... WRITE ORDERED BY col ASC/DESC ... to define the write sort order.","Remove the 'sort-order' property assignment from the SET TBLPROPERTIES clause.","If only reading, fetch the current sort order via DESCRIBE TABLE EXTENDED or the table's sortOrder() API instead of setting it.","Update automation scripts to use the WRITE ORDERED BY syntax for Iceberg tables."],"exampleFix":"-- before\nALTER TABLE t SET TBLPROPERTIES ('sort-order'='id ASC');\n-- after\nALTER TABLE t WRITE ORDERED BY id ASC;","handlingStrategy":"validation","validationCode":"-- Precheck: reject reserved properties before running DDL\n-- (application-side)\nList<String> reserved = Arrays.asList(\"sort-order\", \"identifier-fields\",\n    \"current-snapshot-id\", \"cherry-pick-snapshot-id\", \"format-version\");\nif (props.keySet().stream().anyMatch(reserved::contains)) {\n  throw new IllegalArgumentException(\"Use dedicated DDL for reserved properties\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  spark.sql(alterStatement);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().contains(\"sort-order\")) {\n    // rewrite to ALTER TABLE ... WRITE ORDERED BY\n  }\n}","preventionTips":["Never set reserved Iceberg properties via TBLPROPERTIES","Use WRITE ORDERED BY / SET IDENTIFIER FIELDS for sort orders and identifiers","Check DESCRIBE TABLE EXTENDED to see which properties are managed","Filter reserved keys out of generated DDL in automation"],"tags":["spark","ddl","reserved-property","sort-order"],"backgroundTag":"invalid-config-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"}