apache/iceberg · error · IllegalStateException

Cannot wrap catalog that does not produce BaseTable

Error message

Cannot wrap catalog that does not produce BaseTable

What it means

CatalogHandlers.createTable expects the catalog's result to be a BaseTable so it can wrap the underlying TableMetadata into a LoadTableResponse. If the returned Table is not a BaseTable (e.g. a proxy/wrapper from a custom catalog), this IllegalStateException is thrown — an internal contract violation: catalogs behind the REST handler must produce BaseTable instances.

Solutions

  1. Make the custom catalog return BaseTable (unwrap the delegate's table in createTable)
  2. Unwrap nested wrappers to the underlying BaseTable before returning
  3. Use a catalog implementation known to produce BaseTable
  4. Ensure the wrapper exposes the BaseTable contract (operations(), current metadata)

Example fix

// before
return wrappedTable; // custom wrapper, not BaseTable
// after
Table t = delegateCatalog.createTable(ident, schema, spec, props);
return t instanceof BaseTable ? t : ((BaseTable) unwrap(t));
Defensive patterns

Strategy: type-guard

Validate before calling

Table t = catalog.createTable(ident, schema, spec, props);
if (!(t instanceof BaseTable)) {
  throw new IllegalArgumentException("Catalog must return BaseTable, got: " + t.getClass());
}

Type guard

boolean isBaseTable(Table t) {
  return t instanceof BaseTable;
}

Try / catch

try {
  CatalogHandlers.createTable(catalog, ns, request);
} catch (IllegalStateException e) {
  if (e.getMessage().contains("BaseTable")) {
    // fix the catalog adapter to return BaseTable
  }
}

Prevention

When it happens

Trigger: Wiring a custom Catalog implementation that returns wrapped Table objects (not BaseTable) into the REST catalog handler and creating a table through it.

Common situations: Custom or third-party catalog adapters (routing, caching, multi-tenant proxies) returning decorated Table wrappers; forgetting to unwrap to the delegate's BaseTable.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/rest/CatalogHandlers.java:465

    request.validate();

    TableIdentifier ident = TableIdentifier.of(namespace, request.name());
    Table table =
        catalog
            .buildTable(ident, request.schema())
            .withLocation(request.location())
            .withPartitionSpec(request.spec())
            .withSortOrder(request.writeOrder())
            .withProperties(request.properties())
            .create();

    if (table instanceof BaseTable) {
      return LoadTableResponse.builder()
          .withTableMetadata(((BaseTable) table).operations().current())
          .build();
    }

    throw new IllegalStateException("Cannot wrap catalog that does not produce BaseTable");
  }

  public static LoadTableResponse registerTable(
      Catalog catalog, Namespace namespace, RegisterTableRequest request) {
    request.validate();

    TableIdentifier identifier = TableIdentifier.of(namespace, request.name());
    Table table =
        catalog.registerTable(identifier, request.metadataLocation(), request.overwrite());
    if (table instanceof BaseTable) {
      return LoadTableResponse.builder()
          .withTableMetadata(((BaseTable) table).operations().current())
          .build();
    }

    throw new IllegalStateException("Cannot wrap catalog that does not produce BaseTable");
  }

View on GitHub (pinned to 86d9c8fc54)