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

CreateOrReplaceBranchExec applies WAP/branch management (manageSnapshots.createOrReplaceBranch...) only when the resolved table is an Iceberg table. Non-Iceberg Table implementations hit the default case and throw this UnsupportedOperationException because snapshot references (branches) do not exist outside Iceberg.

Solutions

  1. Qualify the table with the Iceberg catalog: `ALTER TABLE iceberg_catalog.db.t CREATE OR REPLACE BRANCH b ...`.
  2. Confirm the catalog config: spark.sql.catalog.<name>=org.apache.iceberg.spark.SparkCatalog.
  3. Verify the target table's format is Iceberg; migrate it if branching is required.
  4. If the goal is versioning on a non-Iceberg table, use that engine's own mechanism (e.g. Delta branches) instead.

Example fix

-- before
ALTER TABLE spark_catalog.db.t CREATE OR REPLACE BRANCH audit
-- after
ALTER TABLE iceberg_catalog.db.t CREATE OR REPLACE BRANCH audit
Defensive patterns

Strategy: type-guard

Validate before calling

// Scala: confirm catalog is Iceberg before branch DDL
require(
  spark.conf.getOption(s"spark.sql.catalog.$catalogName")
    .exists(_.contains("org.apache.iceberg.spark.SparkCatalog")),
  s"$catalogName is not an Iceberg catalog")

Type guard

// Scala
 table match {
  case st: org.apache.iceberg.spark.SparkTable => st.table() // Iceberg table
  case _ => null // branch DDL unsupported
}

Try / catch

// Scala
try {
  spark.sql(s"ALTER TABLE $ident CREATE OR REPLACE BRANCH $branch")
} catch {
  case _: UnsupportedOperationException => log.error(s"$ident is not Iceberg; branching unavailable")
}

Prevention

When it happens

Trigger: Running `ALTER TABLE ... CREATE OR REPLACE BRANCH ...` against a table resolved through a non-Iceberg catalog (plain Spark V2 datasource tables, Hive tables, Delta tables, etc.).

Common situations: Wrong catalog in a multi-catalog environment, table names without the Iceberg catalog prefix resolving to spark_catalog, or assuming a foreign format supports Iceberg branching.

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/8f7ba226dd2e16ef. Report an issue: GitHub.

Appendix: source

Thrown at spark/v4.1/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)