apache/iceberg · error · UnsupportedOperationException
Cannot drop identifier fields in non-Iceberg table: $table
Error message
Cannot drop identifier fields in non-Iceberg table: $table
What it means
DropIdentifierFieldsExec throws this when ALTER TABLE ... DROP IDENTIFIER FIELDS is executed against a table that is not an Iceberg SparkTable. Identifier fields are an Iceberg schema concept (upsert/delete keys), so only Iceberg's UpdateSchema API supports removing them. The executor pattern-matches on SparkTable and throws UnsupportedOperationException for any other V2 table.
Solutions
- Confirm the table is Iceberg and qualify it with the Iceberg catalog name in the statement
- Check `SHOW CATALOGS` / the catalog used in session config to ensure you target the Iceberg catalog
- Remove identifier-field DDL from scripts for non-Iceberg tables, or migrate the table to Iceberg first
Example fix
// before ALTER TABLE spark_catalog.default.users DROP IDENTIFIER FIELDS user_id; // after ALTER TABLE iceberg_catalog.default.users DROP IDENTIFIER FIELDS user_id;
Defensive patterns
Strategy: validation
Validate before calling
val table = spark.sessionState.catalogManager.currentCatalog.asTableCatalog.loadTable(ident) require(table.isInstanceOf[org.apache.iceberg.spark.source.SparkTable], s"$ident is not an Iceberg table")
Type guard
def supportsIdentifierFields(t: org.apache.spark.sql.connector.catalog.Table): Boolean = t.isInstanceOf[org.apache.iceberg.spark.source.SparkTable]
Try / catch
try { spark.sql(s"ALTER TABLE $ident DROP IDENTIFIER FIELDS id") } catch { case e: UnsupportedOperationException if e.getMessage.contains("non-Iceberg") => throw new IllegalStateException(s"Identifier fields require an Iceberg table: $ident", e) } Prevention
- Verify table format with DESCRIBE TABLE / DESCRIBE EXTENDED before Iceberg schema DDL
- Use explicit catalog prefixes in all DDL scripts
- Separate Iceberg-only DDL into scripts that only run against Iceberg catalogs
When it happens
Trigger: Executing `ALTER TABLE ... DROP IDENTIFIER FIELDS id` where the resolved table is from a non-Iceberg catalog (Delta, JDBC, custom V2), failing the `iceberg: SparkTable` match.
Common situations: Wrong catalog prefix in SQL; copy-pasted Iceberg DDL scripts run against tables migrated off Iceberg; environments where multiple catalogs are registered and the default is not Iceberg.
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
- Cannot set identifier fields in non-Iceberg table: $table
- Cannot drop branch on non-Iceberg table: $table
- Cannot drop identifier fields in non-Iceberg table: $table
- Cannot drop partition field in non-Iceberg table: $table
- Cannot drop tag on non-Iceberg table: $table
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/99ec3cb609a8cd83.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.1/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DropIdentifierFieldsExec.scala:58
for (name <- fields) {
Preconditions.checkArgument(
schema.findField(name) != null,
"Cannot complete drop identifier fields operation: field %s not found",
name)
Preconditions.checkArgument(
identifierFieldNames.contains(name),
"Cannot complete drop identifier fields operation: %s is not an identifier field",
name)
identifierFieldNames.remove(name)
}
iceberg.table
.updateSchema()
.setIdentifierFields(identifierFieldNames)
.commit();
case table =>
throw new UnsupportedOperationException(
s"Cannot drop identifier fields in non-Iceberg table: $table")
}
Nil
}
override def simpleString(maxFields: Int): String = {
s"DropIdentifierFields ${catalog.name}.${ident.quoted} (${fields.quoted})";
}
}
View on GitHub (pinned to 86d9c8fc54)