apache/iceberg · error
Cannot set identifier fields in non-Iceberg table: $table
Error message
Cannot set identifier fields in non-Iceberg table: $table
What it means
SetIdentifierFieldsExec throws this UnsupportedOperationException when a SET IDENTIFIER FIELDS statement targets a non-Iceberg table. Setting identifier fields requires Iceberg's updateSchema().setIdentifierFields() API, exposed only by SparkTable instances wrapping Iceberg tables. Any other resolved table reaches the fallback throwing case.
Source
Thrown at spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/SetIdentifierFieldsExec.scala:42
import org.apache.spark.sql.connector.catalog.Identifier
import org.apache.spark.sql.connector.catalog.TableCatalog
import scala.jdk.CollectionConverters._
case class SetIdentifierFieldsExec(catalog: TableCatalog, ident: Identifier, fields: Seq[String])
extends LeafV2CommandExec {
import org.apache.spark.sql.connector.catalog.CatalogV2Implicits._
override lazy val output: Seq[Attribute] = Nil
override protected def run(): Seq[InternalRow] = {
catalog.loadTable(ident) match {
case iceberg: SparkTable =>
iceberg.table
.updateSchema()
.setIdentifierFields(fields.asJava)
.commit();
case table =>
throw new UnsupportedOperationException(
s"Cannot set identifier fields in non-Iceberg table: $table")
}
Nil
}
override def simpleString(maxFields: Int): String = {
s"SetIdentifierFields ${catalog.name}.${ident.quoted} (${fields.quoted})";
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Verify the provider with DESC TABLE EXTENDED and confirm iceberg.
- Qualify the statement with the Iceberg catalog: ALTER TABLE iceberg_catalog.db.tbl SET IDENTIFIER FIELDS id.
- Register the catalog as org.apache.iceberg.spark.SparkCatalog so identifiers produce SparkTables.
- Migrate the table to Iceberg if identifier fields are needed for row-level operations.
Example fix
-- before ALTER TABLE db.events SET IDENTIFIER FIELDS event_id; -- non-Iceberg -- after ALTER TABLE iceberg_catalog.db.events SET IDENTIFIER FIELDS event_id;
Defensive patterns
Strategy: validation
Validate before calling
val provider = spark.sql("DESC TABLE EXTENDED cat.db.tbl").where("col_name = 'Provider'").first().getString(1)
require(provider == "iceberg", "SET IDENTIFIER FIELDS requires Iceberg") 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("ALTER TABLE cat.db.tbl SET IDENTIFIER FIELDS event_id") } catch { case e: UnsupportedOperationException if e.getMessage.contains("non-Iceberg") => log.warn("identifier fields require an Iceberg table") } Prevention
- Run identifier-field DDL only against Iceberg-qualified table names
- Check Provider in DESC TABLE EXTENDED before schema DDL
- Register catalogs with org.apache.iceberg.spark.SparkCatalog so DDL resolves to Iceberg tables
When it happens
Trigger: Running ALTER TABLE ... SET IDENTIFIER FIELDS <cols> where the resolved table does not match `iceberg: SparkTable`, so the pattern match fails.
Common situations: Identifier-field DDL executed on Hive/Delta tables; wrong catalog binding so the command resolves through a non-Iceberg provider; teams rolling out row-level-dedupe features onto tables not yet migrated to 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 drop identifier fields in non-Iceberg table: $table
- Unknown move type:
- Renaming a view is not supported by catalog: ${catalogName}
- Cannot convert predicate to SQL: <pred>
- Cannot convert term to SQL: <term>
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/fd939ccd9f2eb71e.
Report an issue: GitHub.