apache/iceberg · error · UnsupportedOperationException

Table does not implement

Error message

Table does not implement %s: %s (%s)

What it means

RollbackStagedTable delegates operations by casting its wrapped table to required interfaces (RowLevelOperation's scan/write builders etc.); callReturning throws UnsupportedOperationException 'Table does not implement %s: %s (%s)' when the underlying table lacks the needed interface. This means the targeted table object can't support the requested row-level/rollback capability.

Solutions

  1. Ensure the table is loaded from the Iceberg catalog so the correct SparkTable implementation (with all capability interfaces) is used.
  2. Align the iceberg-spark runtime jar version with your Spark version (3.5) — version skew causes missing interfaces on the wrapped table.
  3. Verify the SQL target is a real Iceberg table, not a view/temp view/foreign table; row-level ops require table implementations that support the operation.
  4. If implementing a custom Catalog/TablePlugin, make your table implement the required interfaces (e.g. SupportsRowLevelOperations) that RollbackStagedTable expects.

Example fix

// before
// custom catalog returns a bare table
return new MySimpleTable(...);
// after
public class MySparkTable extends SparkTable implements SupportsRowLevelOperations { ... }
return new MySparkTable(...);
Defensive patterns

Strategy: validation

Validate before calling

Table sparkTable = ((SparkTable) catalog.loadTable(ident)).table();
if (!(sparkTable instanceof SupportsRowLevelOperations)) {
  throw new IllegalStateException("Target table does not support row-level operations");
}

Try / catch

try { spark.sql("DELETE FROM cat.db.t WHERE id = 1"); } catch (UnsupportedOperationException e) { LOG.error("Table lacks required interface: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Spark DELETE/UPDATE/MERGE INTO (row-level operations) or rollback against an Iceberg table whose implementation does not implement the required internal interface (e.g. a v1-table wrapper, a foreign Spark table, or a catalog returning a plain SparkTable without extendsTable/rollback support).

Common situations: Running MERGE/DELETE against a table from a non-Iceberg catalog masquerading as Iceberg; mixed Iceberg versions where Spark 3.5 bundles an older table wrapper lacking newer interfaces; pointing a row-level SQL at a view or temporary staged table that lacks the interface.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/RollbackStagedTable.java:136

  @Override
  public WriteBuilder newWriteBuilder(LogicalWriteInfo info) {
    return callReturning(SupportsWrite.class, t -> t.newWriteBuilder(info));
  }

  private <T> void call(Class<? extends T> requiredClass, Consumer<T> task) {
    callReturning(
        requiredClass,
        inst -> {
          task.accept(inst);
          return null;
        });
  }

  private <T, R> R callReturning(Class<? extends T> requiredClass, Function<T, R> task) {
    if (requiredClass.isInstance(table)) {
      return task.apply(requiredClass.cast(table));
    } else {
      throw new UnsupportedOperationException(
          String.format(
              "Table does not implement %s: %s (%s)",
              requiredClass.getSimpleName(), table.name(), table.getClass().getName()));
    }
  }
}

View on GitHub (pinned to 86d9c8fc54)