{"record":{"id":"a4e5afc61636a349","repo":"apache/iceberg","slug":"cannot-create-or-replace-branch-on-non-iceberg-tab","errorCode":null,"errorMessage":"Cannot create or replace branch on non-Iceberg table: $table","messagePattern":"Cannot create or replace 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/CreateOrReplaceBranchExec.scala","lineNumber":93,"sourceCode":"          safeCreateBranch()\n        }\n\n        if (branchOptions.numSnapshots.nonEmpty) {\n          manageSnapshots.setMinSnapshotsToKeep(branch, branchOptions.numSnapshots.get.toInt)\n        }\n\n        if (branchOptions.snapshotRetain.nonEmpty) {\n          manageSnapshots.setMaxSnapshotAgeMs(branch, branchOptions.snapshotRetain.get)\n        }\n\n        if (branchOptions.snapshotRefRetain.nonEmpty) {\n          manageSnapshots.setMaxRefAgeMs(branch, branchOptions.snapshotRefRetain.get)\n        }\n\n        manageSnapshots.commit()\n\n      case table =>\n        throw new UnsupportedOperationException(\n          s\"Cannot create or replace branch on non-Iceberg table: $table\")\n    }\n\n    Nil\n  }\n\n  override def simpleString(maxFields: Int): String = {\n    s\"CreateOrReplace branch: $branch for table: ${ident.quoted}\"\n  }\n}\n","sourceCodeStart":75,"sourceCodeEnd":104,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/CreateOrReplaceBranchExec.scala#L75-L104","documentation":"This UnsupportedOperationException is thrown by CreateOrReplaceBranchExec when a CREATE OR REPLACE BRANCH SQL command targets a table that is not an Iceberg table. The Spark V2 catalog resolved the identifier, but the underlying SparkTable does not wrap an Iceberg table that supports snapshot management, so only SparkTable instances exposing manageSnapshots can execute the plan. It indicates the target table's provider does not support Iceberg branch operations.","triggerScenarios":"Running CREATE OR REPLACE BRANCH <name> (with optional RETAIN clauses) against a table whose provider is not Iceberg, or against a session catalog whose table does not match `iceberg: SparkTable` in the plan's pattern match.","commonSituations":"Pointing the branch DDL at a Delta/Parquet/Hive table by mistake; forgetting to USE a catalog registered with SparkCatalog that would produce a SparkTable; using a fallback catalog that resolves to a non-Iceberg V2 table.","solutions":["Verify the target table is an Iceberg table: DESC TABLE EXTENDED <table> and check the Provider is 'iceberg'.","Run the command against the correct catalog: USE <iceberg_catalog> or fully qualify catalog.table in the DDL.","Register the Iceberg catalog in Spark conf (spark.sql.catalog.<name>=org.apache.iceberg.spark.SparkCatalog) and re-run the statement.","If you need branches, migrate the data into an Iceberg table first."],"exampleFix":"-- before\nCREATE OR REPLACE BRANCH audit_branch IN prod_db.events; -- events is a Delta table\n-- after\nCREATE OR REPLACE BRANCH audit_branch IN iceberg_catalog.prod_db.events;","handlingStrategy":"validation","validationCode":"val provider = spark.table(\"catalog.db.tbl\").queryExecution.logical.collect { case t: org.apache.spark.sql.catalyst.catalog.CatalogTable => t.provider }.headOption\nif (!provider.contains(\"iceberg\")) throw new IllegalStateException(\"target is not an Iceberg table\")","typeGuard":"def isIcebergTable(table: org.apache.spark.sql.connector.catalog.Table): Boolean = table.isInstanceOf[org.apache.iceberg.spark.source.SparkTable]","tryCatchPattern":"try { spark.sql(\"CREATE OR REPLACE BRANCH b IN cat.db.tbl\") } catch { case e: UnsupportedOperationException if e.getMessage.contains(\"non-Iceberg table\") => log.warn(s\"target not Iceberg: ${e.getMessage}\") }","preventionTips":["Always qualify branch DDL with the Iceberg catalog name","Check Provider in DESC TABLE EXTENDED before snapshot-ref DDL","Register only Iceberg-backed catalogs for snapshot management commands"],"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-14T11:17:12.474Z"}