apache/iceberg · error · UnsupportedOperationException

${this.getClass().getName()} does not support operations()

Error message

${this.getClass().getName()} does not support operations()

What it means

SerializableMetadataTable is the serializable wrapper for Iceberg metadata tables (e.g. table.files, table.history, table.refs). Unlike the plain SerializableTable, whose operations() lazily wraps a StaticTableOperations, metadata tables are instantiated through MetadataTableUtils and expose no StaticTableOperations, so operations() is intentionally unimplemented and always throws UnsupportedOperationException.

Source

Thrown at core/src/main/java/org/apache/iceberg/SerializableTable.java:461

  public static class SerializableMetadataTable extends SerializableTable {
    private final MetadataTableType type;
    private final String baseTableName;

    protected SerializableMetadataTable(BaseMetadataTable metadataTable) {
      super(metadataTable);
      this.type = metadataTable.metadataTableType();
      this.baseTableName = metadataTable.table().name();
    }

    @Override
    protected Table newTable(TableOperations ops, String tableName) {
      return MetadataTableUtils.createMetadataTableInstance(ops, baseTableName, tableName, type);
    }

    @Override
    public StaticTableOperations operations() {
      throw new UnsupportedOperationException(
          this.getClass().getName() + " does not support operations()");
    }

    public MetadataTableType type() {
      return type;
    }
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Do not call operations() on metadata tables; instead use the metadata-table-specific APIs (e.g. scan via newScan(), MetadataTableType via type()).
  2. If the underlying base table's operations are needed, keep a reference to the original BaseMetadataTable (or reload it from the catalog) and call operations() on the base table, not the serialized wrapper.
  3. Recreate the metadata table on demand with MetadataTableUtils.createMetadataTableInstance(ops, baseTableName, tableName, type) instead of deserializing it.

Example fix

// before
TableOperations ops = ((HasTableOperations) serializedMetadataTable).operations(); // throws

// after
Table base = catalog.loadTable(baseTableLocation);
MetadataTableUtils.createMetadataTableInstance(base.operations(), baseTableName, name, type);
Defensive patterns

Strategy: type-guard

Validate before calling

if (table instanceof org.apache.iceberg.SerializableTable.SerializableMetadataTable) {
  // operations() is unsupported; use newScan()/type() or recreate via MetadataTableUtils
}

Type guard

boolean supportsOperationsAccess(Table t) {
  return t instanceof org.apache.iceberg.HasTableOperations
      && !(t instanceof org.apache.iceberg.SerializableTable.SerializableMetadataTable);
}

Try / catch

try {
  TableOperations ops = ((HasTableOperations) table).operations();
  // ...
} catch (UnsupportedOperationException e) {
  // recreate the metadata table from the base table's operations
  Table base = catalog.loadTable(baseTableLocation);
  Table meta = MetadataTableUtils.createMetadataTableInstance(
      ((HasTableOperations) base).operations(), baseTableName, tableName, type);
}

Prevention

When it happens

Trigger: Calling operations() on a serialized metadata table (SerializableMetadataTable), typically obtained when a metadata table instance was passed through serialization (broadcast/closure) or cast to a type exposing operations(); code paths that require HasTableOperations on metadata tables also hit this.

Common situations: Engine integration or utility code that inspects TableOperations of a metadata table after distribution; Kryo/Java deserialization of metadata tables (e.g. files/meta tables) in Spark executors followed by API calls needing operations().

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