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

  1. Ensure the target is an Iceberg table and qualify it with the Iceberg catalog name
  2. List existing tags first (e.g. via metadata table or SELECT * FROM table.refs) to confirm tag management applies
  3. 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

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


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)