apache/iceberg · error · UnsupportedOperationException

Cannot retrieve UUID for table

Error message

Cannot retrieve UUID for table ${table.name()}

What it means

uuid(Table) retrieves a table's UUID from its TableOperations metadata. It supports plain Iceberg tables (HasTableOperations) and metadata tables (BaseMetadataTable); any other Table implementation whose operations/metadata are not accessible throws UnsupportedOperationException.

Solutions

  1. Ensure you pass the underlying org.apache.iceberg.Table (unwrap wrappers before calling uuid())
  2. Make custom Table implementations implement HasTableOperations so operations() is accessible
  3. For metadata tables, wrap them in a BaseMetadataTable subclass or fetch the UUID from the base table directly

Example fix

// before
Table wrapped = new MyWrapperTable(inner);
String uuid = Spark3Util.uuid(wrapped); // throws
// after
String uuid = Spark3Util.uuid(inner); // underlying table implements HasTableOperations
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(table instanceof HasTableOperations) && !(table instanceof BaseMetadataTable)) { /* obtain UUID another way */ }

Type guard

boolean hasAccessibleUuid(Table t) { return t instanceof HasTableOperations || t instanceof BaseMetadataTable; }

Try / catch

try { return Spark3Util.uuid(table); } catch (UnsupportedOperationException e) { return null; /* fall back to table.name() as key */ }

Prevention

When it happens

Trigger: Calling Spark3Util.uuid(table) with a Table wrapper that neither implements HasTableOperations nor is a BaseMetadataTable — e.g. a custom or third-party Table implementation, or a wrapped/serializable table hiding its operations.

Common situations: Using uuid() in Spark plans/actions against a proxied table (e.g. certain cached or mocking wrappers); integrating a custom catalog whose Table impl doesn't expose operations; version drift where a wrapper class stopped implementing HasTableOperations.

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

Appendix: source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java:1051

    Preconditions.checkArgument(
        namespace.length <= 1,
        "Cannot convert %s to a Spark v1 identifier, namespace contains more than 1 part",
        identifier);

    String table = identifier.name();
    Option<String> database = namespace.length == 1 ? Option.apply(namespace[0]) : Option.empty();
    return org.apache.spark.sql.catalyst.TableIdentifier.apply(table, database);
  }

  public static String baseTableUUID(org.apache.iceberg.Table table) {
    if (table instanceof HasTableOperations) {
      TableOperations ops = ((HasTableOperations) table).operations();
      return ops.current().uuid();
    } else if (table instanceof BaseMetadataTable) {
      return ((BaseMetadataTable) table).table().operations().current().uuid();
    } else {
      throw new UnsupportedOperationException("Cannot retrieve UUID for table " + table.name());
    }
  }

  private static class DescribeSortOrderVisitor implements SortOrderVisitor<String> {
    private static final DescribeSortOrderVisitor INSTANCE = new DescribeSortOrderVisitor();

    private DescribeSortOrderVisitor() {}

    @Override
    public String field(
        String sourceName,
        int sourceId,
        org.apache.iceberg.SortDirection direction,
        NullOrder nullOrder) {
      return String.format("%s %s %s", sourceName, direction, nullOrder);
    }

    @Override

View on GitHub (pinned to 86d9c8fc54)