apache/iceberg · error · UnsupportedOperationException
Cannot drop tag on non-Iceberg table: $table
Error message
Cannot drop tag on non-Iceberg table: $table
What it means
DropTagExec throws this when ALTER TABLE ... DROP TAG is executed on a table that is not an Iceberg SparkTable. Tags (named snapshot references) exist only in Iceberg's ref model, so the extensions executor unwraps the table and throws UnsupportedOperationException for any other implementation. Like branches, tags cannot be dropped on foreign catalogs.
Solutions
- Ensure the target is an Iceberg table and qualify it with the Iceberg catalog name
- List existing tags first (e.g. via metadata table or SELECT * FROM table.refs) to confirm tag management applies
- Remove tag DDL from pipelines handling non-Iceberg tables, or migrate those tables to Iceberg
Example fix
// before ALTER TABLE other_catalog.db.t DROP TAG etl_snapshot; // after ALTER TABLE iceberg_catalog.db.t DROP TAG etl_snapshot;
Defensive patterns
Strategy: validation
Validate before calling
val loaded = catalog.loadTable(ident) require(loaded.isInstanceOf[org.apache.iceberg.spark.source.SparkTable], s"Tag management requires Iceberg: $ident")
Type guard
def isIcebergTable(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 TAG $tag") } catch { case e: UnsupportedOperationException if e.getMessage.contains("non-Iceberg") => log.warn(s"Skipping tag drop on non-Iceberg table $ident") } Prevention
- Only run snapshot-reference DDL against Iceberg-qualified table names
- Inspect table.refs / metadata before tag operations
- Keep Iceberg maintenance jobs pointed at the Iceberg catalog explicitly
When it happens
Trigger: Running `ALTER TABLE ... DROP TAG <tag>` where the resolved table comes from a non-Iceberg catalog, missing the `iceberg: SparkTable` match in run().
Common situations: Snapshot-retention scripts that manage tags applied to the wrong tables; catalogs switched after a migration; users confusing V2 catalog capabilities with Iceberg features.
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 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 replace partition field in non-Iceberg table: $table
- Cannot set identifier fields in non-Iceberg table: $table
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/18a72158fd07b95a.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.1/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DropTagExec.scala:43
import org.apache.spark.sql.connector.catalog.TableCatalog
case class DropTagExec(catalog: TableCatalog, ident: Identifier, tag: String, ifExists: Boolean)
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 =>
val ref = iceberg.table().refs().get(tag)
if (ref != null || !ifExists) {
iceberg.table().manageSnapshots().removeTag(tag).commit()
}
case table =>
throw new UnsupportedOperationException(s"Cannot drop tag on non-Iceberg table: $table")
}
Nil
}
override def simpleString(maxFields: Int): String = {
s"DropTag tag: ${tag} for table: ${ident.quoted}"
}
}
View on GitHub (pinned to 86d9c8fc54)