apache/iceberg · error · UnsupportedOperationException
Cannot create tag to non-Iceberg table: $table
Error message
Cannot create tag to non-Iceberg table: $table
What it means
This UnsupportedOperationException is thrown by CreateOrReplaceTagExec when the target of ALTER TABLE ... CREATE TAG is a Spark table that is not an Iceberg table. The Spark extensions pattern-match the resolved table against SparkTable (the Iceberg wrapper); any other catalog/table implementation falls into the catch-all case and fails. Tags are an Iceberg-specific snapshot reference feature, so non-Iceberg tables cannot support them.
Source
Thrown at spark/v4.0/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/CreateOrReplaceTagExec.scala:77
manageSnapshot.createTag(tag, snapshotId)
} else if (replace) {
manageSnapshot.replaceTag(tag, snapshotId)
} else {
if (refExists && ifNotExists) {
return Nil
}
manageSnapshot.createTag(tag, snapshotId)
}
if (tagOptions.snapshotRefRetain.nonEmpty) {
manageSnapshot.setMaxRefAgeMs(tag, tagOptions.snapshotRefRetain.get)
}
manageSnapshot.commit()
case table =>
throw new UnsupportedOperationException(s"Cannot create tag to non-Iceberg table: $table")
}
Nil
}
override def simpleString(maxFields: Int): String = {
s"Create tag: $tag for table: ${ident.quoted}"
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Verify the target table is an Iceberg table (check its provider with DESCRIBE TABLE EXTENDED or SHOW CREATE TABLE).
- Use an Iceberg catalog (Hadoop/Hive/Nessie/REST) so the table resolves to a SparkTable.
- If using Spark session catalog, ensure the table was created/migrated with Iceberg (e.g. via a migration procedure).
- If the operation may not exist, guard the ALTER TABLE with IF EXISTS semantics or check the table type first.
Example fix
// before ALTER TABLE delta_table CREATE TAG etl_2026_01; // after ALTER TABLE iceberg_catalog.db.events CREATE TAG etl_2026_01;
Defensive patterns
Strategy: validation
Validate before calling
val table = spark.sessionState.catalogManager.currentCatalog.asTableCatalog.loadTable(ident) if (!table.isInstanceOf[org.apache.iceberg.spark.SparkTable]) throw new IllegalStateException(s"$ident is not an Iceberg table; CREATE TAG requires Iceberg")
Type guard
def isIcebergTable(t: org.apache.spark.sql.connector.catalog.Table): Boolean = t.isInstanceOf[org.apache.iceberg.spark.SparkTable]
Try / catch
try { spark.sql(s"ALTER TABLE $ident CREATE TAG $tag") } catch { case e: UnsupportedOperationException if e.getMessage.contains("non-Iceberg table") => log.warn(s"$ident is not an Iceberg table; skipping tag creation") } Prevention
- Always qualify Iceberg DDL with the Iceberg catalog name
- Check table provider with DESCRIBE TABLE EXTENDED before Iceberg-specific DDL
- Keep Iceberg operations in scripts scoped to Iceberg catalogs
- List table providers in the environment and filter maintenance jobs accordingly
When it happens
Trigger: Running ALTER TABLE ... CREATE TAG (or CREATE OR REPLACE TAG) against a table resolved through a non-Iceberg DataSource V2 catalog (e.g. Delta, Parquet-based, or a plain Spark catalog table).
Common situations: Pointing the SQL at the wrong table name; a session catalog that resolves to a non-Iceberg provider; using a metastore where the table was migrated away from Iceberg; copy-pasting Iceberg SQL onto a Delta table.
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
- Renaming a view is not supported by catalog: ${catalogName}
- Cannot convert predicate to SQL: <pred>
- Cannot convert term to SQL: <term>
- Cannot retrieve UUID for table <table.name()>
- Unsupported task group for row-based reads: ${partition.task
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/1d832d98af3c8e64.
Report an issue: GitHub.