{"record":{"id":"a44b10fb0f450083","repo":"apache/iceberg","slug":"cannot-specify-the-identifier-fields-because-it-a44b10","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java","lineNumber":346,"sourceCode":"    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\n    try {\n      org.apache.iceberg.Table table = icebergCatalog.loadTable(buildIdentifier(ident));\n      commitChanges(\n          table, setLocation, setSnapshotId, pickSnapshotId, propertyChanges, schemaChanges);","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java#L328-L364","documentation":"Validation in SparkCatalog.alterTable: a SetProperty change targeted the reserved 'identifier-fields' table property. Identifier fields cannot be set as properties; they must be managed with ALTER TABLE ... SET IDENTIFIER FIELDS, so the property change is rejected during change classification (before any update is applied).","triggerScenarios":"ALTER TABLE ... SET TBLPROPERTIES ('identifier-fields' = '...') or TableChange.setProperty(\"identifier-fields\", ...) sent through alterTable.","commonSituations":"Blind property-sync scripts that re-apply every property from SHOW TBLPROPERTIES output; migrations between environments that include reserved properties; manual edits of table metadata copied as SQL.","solutions":["Use ALTER TABLE ... SET IDENTIFIER FIELDS col1, col2 instead of setting the property.","Exclude 'identifier-fields' from any generic property re-application script.","If identifier fields need to change, use the dedicated clause (or clear them first) per Iceberg's identifier-field semantics.","Audit generated DDL for reserved property names before executing."],"exampleFix":"// before\nspark.sql(\"ALTER TABLE prod.db.users SET TBLPROPERTIES ('identifier-fields'='user_id')\");\n// after\nspark.sql(\"ALTER TABLE prod.db.users SET IDENTIFIER FIELDS user_id\");","handlingStrategy":"validation","validationCode":"if (\"identifier-fields\".equalsIgnoreCase(propKey)) {\n  throw new IllegalArgumentException(\"Use SET IDENTIFIER FIELDS instead of setting the property\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  spark.sql(alterSql);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().contains(\"'identifier-fields'\")) {\n    throw new IllegalArgumentException(\"Use ALTER TABLE ... SET IDENTIFIER FIELDS\", e);\n  }\n  throw e;\n}","preventionTips":["Use ALTER TABLE ... SET IDENTIFIER FIELDS for identifier fields.","Filter 'identifier-fields' out of property-sync/replay scripts.","Treat it like 'sort-order' as managed metadata, not a user property.","Validate DDL generators against the reserved-property list."],"tags":["spark","iceberg","alter-table","reserved-property"],"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"}