apache/iceberg · error · UnsupportedOperationException
Cannot create or replace branch on non-Iceberg table: $table
Error message
Cannot create or replace branch on non-Iceberg table: $table
What it means
This UnsupportedOperationException is thrown by Spark's CREATE OR REPLACE BRANCH execution when the resolved table is not an Iceberg table (i.e. not an IcebergSparkTable backing a SparkTable V2 catalog entry). Branch management (snapshot references) is an Iceberg-only feature, so the operation only works when the target table can be matched to an Iceberg table. The error surfaces because the SQL command was routed through the Iceberg extensions but the table itself was loaded from a non-Iceberg provider.
Source
Thrown at spark/v4.2/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/CreateOrReplaceBranchExec.scala:93
safeCreateBranch()
}
if (branchOptions.numSnapshots.nonEmpty) {
manageSnapshots.setMinSnapshotsToKeep(branch, branchOptions.numSnapshots.get.toInt)
}
if (branchOptions.snapshotRetain.nonEmpty) {
manageSnapshots.setMaxSnapshotAgeMs(branch, branchOptions.snapshotRetain.get)
}
if (branchOptions.snapshotRefRetain.nonEmpty) {
manageSnapshots.setMaxRefAgeMs(branch, branchOptions.snapshotRefRetain.get)
}
manageSnapshots.commit()
case table =>
throw new UnsupportedOperationException(
s"Cannot create or replace branch on non-Iceberg table: $table")
}
Nil
}
override def simpleString(maxFields: Int): String = {
s"CreateOrReplace branch: $branch for table: ${ident.quoted}"
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Verify the target table is an Iceberg table (created/registered via an Iceberg catalog) before running branch DDL
- Use the fully qualified table name with the correct Iceberg catalog, e.g. ALTER TABLE iceberg_catalog.db.tbl CREATE BRANCH ...
- Check spark catalog configuration (spark.sql.catalog.<name> = org.apache.iceberg.spark.SparkCatalog) so the table resolves to Iceberg
- If the table is not Iceberg, migrate it to Iceberg first, or use the storage provider's own branching feature instead
Example fix
// before: table in a non-Iceberg catalog ALTER TABLE my_hive_table CREATE BRANCH audit; // after: explicitly target the Iceberg catalog ALTER TABLE iceberg_catalog.db.my_hive_table CREATE BRANCH audit;
Defensive patterns
Strategy: validation
Validate before calling
import org.apache.iceberg.spark.Spark3Util val icebergTable = Spark3Util.loadIcebergTable(spark, fullTableName) require(icebergTable != null, s"$fullTableName is not an Iceberg table")
Type guard
def isIcebergTable(spark: SparkSession, name: String): Boolean = scala.util.Try(Spark3Util.loadIcebergTable(spark, name)).map(_ != null).getOrElse(false)
Prevention
- Always qualify Iceberg DDL with the Iceberg catalog name
- Verify spark.sql.catalog.<name>=org.apache.iceberg.spark.SparkCatalog registration
- Check the table's provider with DESCRIBE TABLE EXTENDED before branch DDL
When it happens
Trigger: Running 'ALTER TABLE ... CREATE OR REPLACE BRANCH ...' (or CREATE BRANCH) against a table that resolves to a non-Iceberg Spark table, e.g. a Delta/Parquet/Hive table, or a table loaded through a generic DataSourceV2 catalog rather than the Iceberg catalog.
Common situations: Pointing the SQL at the wrong catalog or table name; a session catalog alias resolving to a non-Iceberg provider; misconfigured catalog registration so the table is not recognized as Iceberg.
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
- Cannot drop branch on non-Iceberg table: $table
- Renaming a view is not supported by catalog: ${catalogName}
- Cannot convert predicate to SQL: <pred>
- Cannot convert term to SQL: <term>
- Cannot retrieve UUID for table <table.name()>
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/fc7f5d592cdf325d.
Report an issue: GitHub.