apache/iceberg · error · UnsupportedOperationException

org.apache.iceberg.spark.SparkRewriteTableCatalog does not s

Error message

org.apache.iceberg.spark.SparkRewriteTableCatalog does not support time travel

What it means

The version-based loadTable(ident, version) overload on SparkRewriteTableCatalog always throws UnsupportedOperationException because the rewrite catalog operates on the live cached table and cannot resolve versioned (snapshot-id/branch/tag) loads.

Source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkRewriteTableCatalog.java:61

  }

  @Override
  public SparkRewriteTable loadTable(Identifier ident) throws NoSuchTableException {
    validateNoNamespace(ident);

    String groupId = ident.name();
    Table table = TABLE_CACHE.get(groupId);

    if (table == null) {
      throw new NoSuchTableException(ident);
    }

    return new SparkRewriteTable(table, groupId);
  }

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

  @Override
  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, TableInfo tableInfo)
      throws TableAlreadyExistsException {
    throw new UnsupportedOperationException(CLASS_NAME + " does not support creating tables");
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Do not time travel with the rewrite catalog; rewrite always operates on the current table state.
  2. Load the historical snapshot via the regular SparkCatalog: SELECT ... VERSION AS OF, then perform other operations on it.
  3. Remove version/timestamp options from procedure calls targeting the rewrite catalog.

Example fix

// before
Table t = rewriteCatalog.loadTable(ident, "hist-tag");
// after
Table t = sparkCatalog.loadTable(ident, "hist-tag"); // versioned loads go through the real catalog
Defensive patterns

Strategy: validation

Validate before calling

if (catalog instanceof SparkRewriteTableCatalog && version != null) {
  throw new IllegalArgumentException("Time travel is not supported by SparkRewriteTableCatalog");
}

Type guard

boolean supportsTimeTravel(CatalogPlugin c) {
  return !(c instanceof SparkRewriteTableCatalog);
}

Try / catch

try {
  Table t = catalog.loadTable(ident, version);
} catch (UnsupportedOperationException e) {
  Table t = sparkCatalog.loadTable(ident, version); // versioned loads via the real catalog
}

Prevention

When it happens

Trigger: Calling loadTable(ident, "branch-or-tag") on SparkRewriteTableCatalog, or running a Spark rewrite procedure with time travel / versionAsOf options that force a versioned load.

Common situations: Passing time-travel options (versionAsOf/timestampAsOf) to rewrite or maintenance procedures; generic engine code probing the catalog with the versioned overload.

Related errors


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