{"record":{"id":"ea3fbbf74c6d922f","repo":"apache/iceberg","slug":"cannot-wrap-catalog-that-does-not-produce-basetabl","errorCode":null,"errorMessage":"Cannot wrap catalog that does not produce BaseTable","messagePattern":"Cannot wrap catalog that does not produce BaseTable","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/rest/CatalogHandlers.java","lineNumber":465,"sourceCode":"    request.validate();\n\n    TableIdentifier ident = TableIdentifier.of(namespace, request.name());\n    Table table =\n        catalog\n            .buildTable(ident, request.schema())\n            .withLocation(request.location())\n            .withPartitionSpec(request.spec())\n            .withSortOrder(request.writeOrder())\n            .withProperties(request.properties())\n            .create();\n\n    if (table instanceof BaseTable) {\n      return LoadTableResponse.builder()\n          .withTableMetadata(((BaseTable) table).operations().current())\n          .build();\n    }\n\n    throw new IllegalStateException(\"Cannot wrap catalog that does not produce BaseTable\");\n  }\n\n  public static LoadTableResponse registerTable(\n      Catalog catalog, Namespace namespace, RegisterTableRequest request) {\n    request.validate();\n\n    TableIdentifier identifier = TableIdentifier.of(namespace, request.name());\n    Table table =\n        catalog.registerTable(identifier, request.metadataLocation(), request.overwrite());\n    if (table instanceof BaseTable) {\n      return LoadTableResponse.builder()\n          .withTableMetadata(((BaseTable) table).operations().current())\n          .build();\n    }\n\n    throw new IllegalStateException(\"Cannot wrap catalog that does not produce BaseTable\");\n  }\n","sourceCodeStart":447,"sourceCodeEnd":483,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/rest/CatalogHandlers.java#L447-L483","documentation":"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.","triggerScenarios":"Wiring a custom Catalog implementation that returns wrapped Table objects (not BaseTable) into the REST catalog handler and creating a table through it.","commonSituations":"Custom or third-party catalog adapters (routing, caching, multi-tenant proxies) returning decorated Table wrappers; forgetting to unwrap to the delegate's BaseTable.","solutions":["Make the custom catalog return BaseTable (unwrap the delegate's table in createTable)","Unwrap nested wrappers to the underlying BaseTable before returning","Use a catalog implementation known to produce BaseTable","Ensure the wrapper exposes the BaseTable contract (operations(), current metadata)"],"exampleFix":"// before\nreturn wrappedTable; // custom wrapper, not BaseTable\n// after\nTable t = delegateCatalog.createTable(ident, schema, spec, props);\nreturn t instanceof BaseTable ? t : ((BaseTable) unwrap(t));","handlingStrategy":"type-guard","validationCode":"Table t = catalog.createTable(ident, schema, spec, props);\nif (!(t instanceof BaseTable)) {\n  throw new IllegalArgumentException(\"Catalog must return BaseTable, got: \" + t.getClass());\n}","typeGuard":"boolean isBaseTable(Table t) {\n  return t instanceof BaseTable;\n}","tryCatchPattern":"try {\n  CatalogHandlers.createTable(catalog, ns, request);\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"BaseTable\")) {\n    // fix the catalog adapter to return BaseTable\n  }\n}","preventionTips":["Test custom catalogs against the REST handler before deploying","Delegate to a standard catalog and return its BaseTable directly","Avoid double-wrapping Table objects in routing/proxy layers"],"tags":["rest-catalog","basetable","custom-catalog","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}