apache/iceberg · error · UnsupportedOperationException

does not support altering tables

Error message

${CLASS_NAME} does not support altering tables

What it means

SparkRewriteTableCatalog.alterTable always throws UnsupportedOperationException because schema/property changes are not applicable to its procedure-scoped table cache. ALTER TABLE statements routed through this catalog fail immediately.

Solutions

  1. Issue ALTER TABLE through SparkCatalog or another real Iceberg catalog
  2. Verify the catalog binding for the namespace in your session (DESCRIBE / SHOW CATALOGS)
  3. Separate DDL from rewrite procedures in your job
  4. Fix catalog config so user-facing namespaces use SparkCatalog

Example fix

// before
spark.sql("ALTER TABLE prod.db.events ADD COLUMN c INT") // via rewrite catalog
// after
spark.sql("CALL prod.system.rewrite_data_files(table => 'db.events')") // rewrites only
spark.sql("ALTER TABLE prod.db.events ADD COLUMN c INT") // via SparkCatalog
Defensive patterns

Strategy: validation

Validate before calling

val impl = spark.conf.get("spark.sql.catalog.prod.catalog-impl", "")
require(impl != "org.apache.iceberg.spark.SparkRewriteTableCatalog", "ALTER TABLE not supported on rewrite catalog")

Try / catch

try {
  catalog.alterTable(ident, changes: _*)
} catch {
  case _: UnsupportedOperationException => alterViaRealCatalog(ident, changes: _*)
}

Prevention

When it happens

Trigger: Calling alterTable(ident, changes) on a SparkRewriteTableCatalog, e.g. ALTER TABLE ... ADD COLUMN executed while that catalog binding is active.

Common situations: ALTER TABLE routed to the wrong catalog binding; programmatic schema evolution attempts during a rewrite session.

Related errors


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

Appendix: source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkRewriteTableCatalog.java:85

  public SparkTable loadTable(Identifier ident, long timestampMicros) throws NoSuchTableException {
    throw new UnsupportedOperationException(CLASS_NAME + " does not support time travel");
  }

  @Override
  public void invalidateTable(Identifier ident) {
    throw new UnsupportedOperationException(CLASS_NAME + " does not support table invalidation");
  }

  @Override
  public SparkTable createTable(
      Identifier ident, StructType schema, Transform[] partitions, Map<String, String> properties)
      throws TableAlreadyExistsException {
    throw new UnsupportedOperationException(CLASS_NAME + " does not support creating tables");
  }

  @Override
  public SparkTable alterTable(Identifier ident, TableChange... changes) {
    throw new UnsupportedOperationException(CLASS_NAME + " does not support altering tables");
  }

  @Override
  public boolean dropTable(Identifier ident) {
    throw new UnsupportedOperationException(CLASS_NAME + " does not support dropping tables");
  }

  @Override
  public boolean purgeTable(Identifier ident) throws UnsupportedOperationException {
    throw new UnsupportedOperationException(CLASS_NAME + " does not support purging tables");
  }

  @Override
  public void renameTable(Identifier oldIdent, Identifier newIdent) {
    throw new UnsupportedOperationException(CLASS_NAME + " does not support renaming tables");
  }

  @Override

View on GitHub (pinned to 86d9c8fc54)