{"record":{"id":"2ace524abb7b5086","repo":"apache/iceberg","slug":"cannot-create-metadata-table-for-table-s-table-i","errorCode":null,"errorMessage":"Cannot create metadata table for table %s: table is not a base table or does not have table operations","messagePattern":"Cannot create metadata table for table (.+?): table is not a base table or does not have table operations","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/MetadataTableUtils.java","lineNumber":42,"sourceCode":"\npublic class MetadataTableUtils {\n  private MetadataTableUtils() {}\n\n  public static boolean hasMetadataTableName(TableIdentifier identifier) {\n    return MetadataTableType.from(identifier.name()) != null;\n  }\n\n  public static Table createMetadataTableInstance(Table table, MetadataTableType type) {\n    if (table instanceof BaseTable) {\n      return createMetadataTableInstance(table, metadataTableName(table.name(), type), type);\n    } else if (table instanceof HasTableOperations) {\n      return createMetadataTableInstance(\n          ((HasTableOperations) table).operations(),\n          table.name(),\n          metadataTableName(table.name(), type),\n          type);\n    } else {\n      throw new IllegalArgumentException(\n          String.format(\n              \"Cannot create metadata table for table %s: \"\n                  + \"table is not a base table or does not have table operations\",\n              table));\n    }\n  }\n\n  public static Table createMetadataTableInstance(\n      TableOperations ops, String baseTableName, String metadataTableName, MetadataTableType type) {\n    Table baseTable = new BaseTable(ops, baseTableName);\n    return createMetadataTableInstance(baseTable, metadataTableName, type);\n  }\n\n  private static Table createMetadataTableInstance(\n      Table baseTable, String metadataTableName, MetadataTableType type) {\n    switch (type) {\n      case ENTRIES:\n        return new ManifestEntriesTable(baseTable, metadataTableName);","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/MetadataTableUtils.java#L24-L60","documentation":"IllegalArgumentException thrown when creating a metadata table instance for a Table that does not expose TableOperations (does not implement HasTableOperations). Metadata tables (e.g., table.refs, table.files) can only be built from a real base table backed by Iceberg operations, not from wrapped, generic, or foreign Table implementations. It indicates the object passed in is not a plain Iceberg base table.","triggerScenarios":"Calling MetadataTableUtils.createMetadataTableInstance(table, type) (or loading a metadata table like 'table.files') where the Table is a metadata table itself, a REST/view wrapper, or any implementation not implementing HasTableOperations.","commonSituations":"Chaining metadata tables (selecting from a metadata table and creating another metadata table over it); using engine adapters that wrap Table objects; mocking Table in tests without operations.","solutions":["Load the actual base table from the catalog and request the metadata table from it, not from a wrapped/metadata table.","Verify the Table instance implements HasTableOperations before building metadata tables.","Remove double metadata-table naming (e.g., 'tbl.files.files'); query the base table directly.","In tests, use a real TestTables instance that provides TableOperations."],"exampleFix":"// before\nTable files = MetadataTableUtils.createMetadataTableInstance(metadataTable, MetadataTableType.FILES); // IAE\n// after\nTable baseTable = catalog.loadTable(identifier);\nTable files = MetadataTableUtils.createMetadataTableInstance(baseTable, MetadataTableType.FILES);","handlingStrategy":"validation","validationCode":"// guard before calling\nif (!(table instanceof HasTableOperations)) {\n  throw new IllegalArgumentException(\"Load the base table, not: \" + table.name());\n}","typeGuard":"boolean isBaseIcebergTable(Table t) { return t instanceof HasTableOperations; }","tryCatchPattern":"try {\n  Table meta = MetadataTableUtils.createMetadataTableInstance(table, type);\n} catch (IllegalArgumentException e) {\n  // reload base table from catalog\n}","preventionTips":["Create metadata tables only from tables loaded directly from the catalog","Avoid chaining metadata tables on top of metadata tables","Verify table instanceof HasTableOperations in generic tooling"],"tags":["metadata-table","illegal-argument","api-misuse"],"backgroundTag":"invalid-argument-value","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"}