{"record":{"id":"9b8ef3bc817906e4","repo":"apache/iceberg","slug":"cannot-drop-branch-on-non-iceberg-table-table","errorCode":null,"errorMessage":"Cannot drop branch on non-Iceberg table: $table","messagePattern":"Cannot drop branch 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/DropBranchExec.scala","lineNumber":47,"sourceCode":"    ident: Identifier,\n    branch: String,\n    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(branch)\n        if (ref != null || !ifExists) {\n          iceberg.table().manageSnapshots().removeBranch(branch).commit()\n        }\n\n      case table =>\n        throw new UnsupportedOperationException(s\"Cannot drop branch on non-Iceberg table: $table\")\n    }\n\n    Nil\n  }\n\n  override def simpleString(maxFields: Int): String = {\n    s\"DropBranch branch: ${branch} for table: ${ident.quoted}\"\n  }\n}\n","sourceCodeStart":29,"sourceCodeEnd":57,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DropBranchExec.scala#L29-L57","documentation":"DropBranchExec throws this UnsupportedOperationException when a DROP BRANCH statement targets a table that is not an Iceberg table. Dropping a branch requires Iceberg's manageSnapshots().removeBranch() API, which only exists on tables wrapped by SparkTable with an Iceberg backend. The plan's pattern match falls through to the non-Iceberg case and throws.","triggerScenarios":"Running DROP BRANCH <branch> [IF EXISTS] against a non-Iceberg table, i.e. the resolved table does not match `iceberg: SparkTable` in DropBranchExec.run().","commonSituations":"Pointing branch DDL at a Parquet/Hive/Delta table; using a catalog not registered as the Iceberg SparkCatalog; multi-catalog setups where the default catalog resolves to a non-Iceberg provider.","solutions":["Confirm the table provider is iceberg via DESC TABLE EXTENDED.","Qualify the DDL with the Iceberg catalog: DROP BRANCH b IN iceberg_catalog.db.tbl.","Ensure spark.sql.catalog.<name>=org.apache.iceberg.spark.SparkCatalog is configured.","Use IF EXISTS if the branch/table may not support the operation during migrations."],"exampleFix":"-- before\nDROP BRANCH old_branch IN db.events; -- non-Iceberg provider\n-- after\nDROP BRANCH old_branch IN iceberg_catalog.db.events;","handlingStrategy":"validation","validationCode":"val refs = try { Some(spark.sql(\"SELECT * FROM cat.db.tbl.refs\").collect()) } catch { case _: Exception => None }; if (refs.isEmpty) println(\"not an Iceberg table\")","typeGuard":"def isIcebergSparkTable(t: Any): Boolean = t.isInstanceOf[org.apache.iceberg.spark.source.SparkTable]","tryCatchPattern":"try { spark.sql(\"DROP BRANCH b IN cat.db.tbl\") } catch { case e: UnsupportedOperationException if e.getMessage.startsWith(\"Cannot drop branch on non-Iceberg\") => log.warn(\"skip non-Iceberg table\") }","preventionTips":["Qualify DROP BRANCH with the Iceberg catalog","Filter cleanup scripts by table provider == 'iceberg'","Use IF EXISTS to make branch cleanup idempotent"],"tags":["spark","iceberg","unsupported-operation","branches"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}