{"record":{"id":"f5f329f4f0f47e76","repo":"apache/iceberg","slug":"cannot-drop-branch-on-non-iceberg-table-table-f5f329","errorCode":null,"errorMessage":"Cannot drop branch on non-Iceberg table: $table","messagePattern":"Cannot drop branch on non-Iceberg table: \\$table","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.1/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/v4.1/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DropBranchExec.scala#L29-L57","documentation":"This error is thrown by DropBranchExec when the ALTER TABLE ... DROP BRANCH command targets a table resolved through a Spark catalog that is not an Iceberg SparkTable. Iceberg branches only exist on Iceberg tables, so the extensions executor unwraps the DataSourceV2 table and throws UnsupportedOperationException for any other table implementation. The operation is fundamentally unsupported outside Iceberg's snapshot reference model.","triggerScenarios":"Running `ALTER TABLE ... DROP BRANCH <branch>` where the table is registered via a non-Iceberg DataSourceV2 catalog (e.g. Delta, JDBC, or a custom V2 catalog), so the pattern match on `iceberg: SparkTable` falls through to the `case table =>` branch.","commonSituations":"Pointing the SQL at the wrong catalog or table name; migrating a table to another catalog format and then re-running Iceberg branch management SQL; scripts that assume all tables in a session use the Iceberg catalog.","solutions":["Verify the table is an Iceberg table (check the catalog it resolves through) before issuing DROP BRANCH","Qualify the statement with the correct Iceberg catalog: ALTER TABLE iceberg_catalog.db.table DROP BRANCH b1","If the table is not Iceberg, remove branch-management statements from scripts targeting it, or migrate the table to Iceberg","Add `IF EXISTS` does not help here — it only suppresses a missing branch, not a non-Iceberg table; fix the target table instead"],"exampleFix":"// before\nALTER TABLE delta_catalog.db.events DROP BRANCH audit;\n// after\nALTER TABLE iceberg_catalog.db.events DROP BRANCH audit;","handlingStrategy":"validation","validationCode":"import org.apache.iceberg.spark.Spark3Util\nval catalogAndIdent = Spark3Util.catalogAndIdentifier(spark, \"catalog.db.table\")\nval isIceberg = spark.sessionState.catalogManager\n  .catalog(catalogAndIdent.catalog()).asInstanceOf[org.apache.spark.sql.connector.catalog.TableCatalog]\n  .loadTable(catalogAndIdent.identifier()).isInstanceOf[org.apache.iceberg.spark.source.SparkTable]\nif (!isIceberg) throw new IllegalStateException(\"Target table is not an Iceberg table; branch ops unavailable\")","typeGuard":"def isIcebergTable(t: org.apache.spark.sql.connector.catalog.Table): Boolean = t.isInstanceOf[org.apache.iceberg.spark.source.SparkTable]","tryCatchPattern":"try { spark.sql(\"ALTER TABLE cat.db.t DROP BRANCH b1\") } catch { case e: UnsupportedOperationException if e.getMessage.contains(\"non-Iceberg table\") => log.warn(s\"Not an Iceberg table, skipping branch drop: ${e.getMessage}\") }","preventionTips":["Always qualify Iceberg DDL with the Iceberg catalog name","Check the table's provider/format before running Iceberg-specific SQL","Keep one catalog convention per environment to avoid mixed-format targets"],"tags":["spark","spark-extensions","unsupported-operation","branch-management"],"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"}