apache/iceberg · error · UnsupportedOperationException

Cannot create tag to non-Iceberg table: $table

Error message

Cannot create tag to non-Iceberg table: $table

What it means

This UnsupportedOperationException is thrown by CreateOrReplaceTagExec when the target of ALTER TABLE ... CREATE TAG is a Spark table that is not an Iceberg table. The Spark extensions pattern-match the resolved table against SparkTable (the Iceberg wrapper); any other catalog/table implementation falls into the catch-all case and fails. Tags are an Iceberg-specific snapshot reference feature, so non-Iceberg tables cannot support them.

Source

Thrown at spark/v4.0/spark-extensions/src/main/scala/org/apache/spark/sql/execution/datasources/v2/CreateOrReplaceTagExec.scala:77

          manageSnapshot.createTag(tag, snapshotId)
        } else if (replace) {
          manageSnapshot.replaceTag(tag, snapshotId)
        } else {
          if (refExists && ifNotExists) {
            return Nil
          }

          manageSnapshot.createTag(tag, snapshotId)
        }

        if (tagOptions.snapshotRefRetain.nonEmpty) {
          manageSnapshot.setMaxRefAgeMs(tag, tagOptions.snapshotRefRetain.get)
        }

        manageSnapshot.commit()

      case table =>
        throw new UnsupportedOperationException(s"Cannot create tag to non-Iceberg table: $table")
    }

    Nil
  }

  override def simpleString(maxFields: Int): String = {
    s"Create tag: $tag for table: ${ident.quoted}"
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Verify the target table is an Iceberg table (check its provider with DESCRIBE TABLE EXTENDED or SHOW CREATE TABLE).
  2. Use an Iceberg catalog (Hadoop/Hive/Nessie/REST) so the table resolves to a SparkTable.
  3. If using Spark session catalog, ensure the table was created/migrated with Iceberg (e.g. via a migration procedure).
  4. If the operation may not exist, guard the ALTER TABLE with IF EXISTS semantics or check the table type first.

Example fix

// before
ALTER TABLE delta_table CREATE TAG etl_2026_01;
// after
ALTER TABLE iceberg_catalog.db.events CREATE TAG etl_2026_01;
Defensive patterns

Strategy: validation

Validate before calling

val table = spark.sessionState.catalogManager.currentCatalog.asTableCatalog.loadTable(ident)
if (!table.isInstanceOf[org.apache.iceberg.spark.SparkTable])
  throw new IllegalStateException(s"$ident is not an Iceberg table; CREATE TAG requires Iceberg")

Type guard

def isIcebergTable(t: org.apache.spark.sql.connector.catalog.Table): Boolean = t.isInstanceOf[org.apache.iceberg.spark.SparkTable]

Try / catch

try { spark.sql(s"ALTER TABLE $ident CREATE TAG $tag") } catch { case e: UnsupportedOperationException if e.getMessage.contains("non-Iceberg table") => log.warn(s"$ident is not an Iceberg table; skipping tag creation") }

Prevention

When it happens

Trigger: Running ALTER TABLE ... CREATE TAG (or CREATE OR REPLACE TAG) against a table resolved through a non-Iceberg DataSource V2 catalog (e.g. Delta, Parquet-based, or a plain Spark catalog table).

Common situations: Pointing the SQL at the wrong table name; a session catalog that resolves to a non-Iceberg provider; using a metastore where the table was migrated away from Iceberg; copy-pasting Iceberg SQL onto a Delta table.

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/1d832d98af3c8e64. Report an issue: GitHub.