{"record":{"id":"5175d1d47bd572f7","repo":"apache/iceberg","slug":"cannot-drop-tag-on-non-iceberg-table-table","errorCode":null,"errorMessage":"Cannot drop tag on non-Iceberg table: $table","messagePattern":"Cannot drop tag on non-Iceberg table: \\$table","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DropTagExec.scala","lineNumber":43,"sourceCode":"import org.apache.spark.sql.connector.catalog.TableCatalog\n\ncase class DropTagExec(catalog: TableCatalog, ident: Identifier, tag: String, ifExists: Boolean)\n    extends LeafV2CommandExec {\n\n  import org.apache.spark.sql.connector.catalog.CatalogV2Implicits._\n\n  override lazy val output: Seq[Attribute] = Nil\n\n  override protected def run(): Seq[InternalRow] = {\n    catalog.loadTable(ident) match {\n      case iceberg: SparkTable =>\n        val ref = iceberg.table().refs().get(tag)\n        if (ref != null || !ifExists) {\n          iceberg.table().manageSnapshots().removeTag(tag).commit()\n        }\n\n      case table =>\n        throw new UnsupportedOperationException(s\"Cannot drop tag on non-Iceberg table: $table\")\n    }\n\n    Nil\n  }\n\n  override def simpleString(maxFields: Int): String = {\n    s\"DropTag tag: ${tag} for table: ${ident.quoted}\"\n  }\n}\n","sourceCodeStart":25,"sourceCodeEnd":53,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DropTagExec.scala#L25-L53","documentation":"DropTagExec throws this UnsupportedOperationException when a DROP TAG statement targets a non-Iceberg table. Removing a tag needs Iceberg's manageSnapshots().removeTag() API, only available on SparkTable instances wrapping Iceberg tables. Other providers reach the fallback throwing case.","triggerScenarios":"Executing DROP TAG <tag> [IF EXISTS] on a table that does not match `iceberg: SparkTable` in DropTagExec.run().","commonSituations":"Tag DDL aimed at Delta/Hive/Parquet tables; misconfigured default catalog; migration scripts iterating over tables of mixed providers.","solutions":["Confirm the table is Iceberg via DESC TABLE EXTENDED.","Fully qualify the statement: DROP TAG v1 IN iceberg_catalog.db.tbl.","Ensure the catalog is registered as org.apache.iceberg.spark.SparkCatalog.","Skip non-Iceberg tables in batch cleanup scripts (filter by provider)."],"exampleFix":"-- before\nDROP TAG v1 IN db.events; -- non-Iceberg\n-- after\nDROP TAG v1 IN iceberg_catalog.db.events;","handlingStrategy":"validation","validationCode":"val exists = spark.catalog.tableExists(\"cat.db.tbl\") && spark.sql(\"SELECT * FROM cat.db.tbl.refs\").collect().nonEmpty","typeGuard":"def isIcebergSparkTable(t: Any): Boolean = t.isInstanceOf[org.apache.iceberg.spark.source.SparkTable]","tryCatchPattern":"try { spark.sql(\"DROP TAG v1 IN cat.db.tbl\") } catch { case e: UnsupportedOperationException if e.getMessage.startsWith(\"Cannot drop tag on non-Iceberg\") => log.warn(\"skip non-Iceberg table\") }","preventionTips":["Qualify DROP TAG with the Iceberg catalog","Guard batch tag cleanup by provider","Prefer IF EXISTS for idempotent tag removal"],"tags":["spark","iceberg","unsupported-operation","tags"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}