apache/iceberg · error · IllegalStateException

Cannot wrap catalog that does not produce BaseTransaction

Error message

Cannot wrap catalog that does not produce BaseTransaction

What it means

For a create-or-replace request, updateTable builds a Transaction via catalog.buildTable(ident, EMPTY_SCHEMA).createOrReplaceTransaction() and needs a BaseTransaction to access underlyingOps() and apply request requirements/updates; a Transaction of another implementation cannot be wrapped, so the handler throws IllegalStateException.

Solutions

  1. Use a catalog implementation that returns BaseTransaction from createOrReplaceTransaction (e.g. extend BaseMetastoreCatalog)
  2. Avoid wrapping/decorating Transaction objects before the handler consumes them
  3. Align server-side Iceberg dependency versions so transaction classes are the core ones
Defensive patterns

Strategy: type-guard

Validate before calling

Transaction tx = catalog.buildTable(ident, schema).createOrReplaceTransaction();
if (!(tx instanceof BaseTransaction)) {
  throw new IllegalStateException("Catalog must produce BaseTransaction: " + tx.getClass());
}

Type guard

function isBaseTransaction(t) { return t instanceof org.apache.iceberg.BaseTransaction; }

Try / catch

try {
  resp = CatalogHandlers.updateTable(catalog, ident, request);
} catch (IllegalStateException e) {
  // swap to a catalog that produces BaseTransaction
}

Prevention

When it happens

Trigger: POST /v1/{prefix}/namespaces/{ns}/tables with an UpdateTableRequest that is a create/replace, against a catalog whose createOrReplaceTransaction returns a non-BaseTransaction Transaction.

Common situations: Custom Catalog implementations behind the REST adapter; catalogs that return decorated transactions; mismatched Iceberg versions where transaction types differ.

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

Appendix: source

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

      // metadata tables are loaded on the client side, return NoSuchTableException for now
      throw new NoSuchTableException("Table does not exist: %s", ident);
    }

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

  public static LoadTableResponse updateTable(
      Catalog catalog, TableIdentifier ident, UpdateTableRequest request) {
    TableMetadata finalMetadata;
    if (isCreate(request)) {
      // this is a hacky way to get TableOperations for an uncommitted table
      Transaction transaction =
          catalog.buildTable(ident, EMPTY_SCHEMA).createOrReplaceTransaction();
      if (transaction instanceof BaseTransaction) {
        BaseTransaction baseTransaction = (BaseTransaction) transaction;
        finalMetadata = create(baseTransaction.underlyingOps(), request);
      } else {
        throw new IllegalStateException(
            "Cannot wrap catalog that does not produce BaseTransaction");
      }

    } else {
      Table table = catalog.loadTable(ident);
      if (table instanceof BaseTable) {
        TableOperations ops = ((BaseTable) table).operations();
        finalMetadata = commit(ops, request);
      } else {
        throw new IllegalStateException("Cannot wrap catalog that does not produce BaseTable");
      }
    }

    return LoadTableResponse.builder().withTableMetadata(finalMetadata).build();
  }

  public static void renameTable(Catalog catalog, RenameTableRequest request) {
    catalog.renameTable(request.source(), request.destination());

View on GitHub (pinned to 86d9c8fc54)