apache/iceberg · error · java.lang.IllegalArgumentException

Cannot use catalog ( ): not a TableCatalog

Error message

Cannot use catalog %s(%s): not a TableCatalog

What it means

asTableCatalog requires that the resolved Spark CatalogPlugin implements the TableCatalog interface. Catalogs that only support views, functions, or session state cannot host Iceberg tables, so this IllegalArgumentException reports the catalog name and class that failed the check.

Solutions

  1. Point the operation at a catalog that implements TableCatalog (e.g. an Iceberg catalog registered via spark.sql.catalog.<name>).
  2. Set spark.sql.defaultCatalog to a table-capable catalog.
  3. Check the class name in the message — it tells you which CatalogPlugin was resolved and whether that's what you intended.
  4. Register the Iceberg catalog explicitly and qualify the table name with it: my_catalog.db.table.

Example fix

// before
spark.conf.set("spark.sql.defaultCatalog", "spark_catalog");
CREATE TABLE t (...) USING iceberg; // throws
// after
spark.conf.set("spark.sql.defaultCatalog", "iceberg_catalog");
CREATE TABLE t (...) USING iceberg; // ok
Defensive patterns

Strategy: type-guard

Validate before calling

// Java/Scala check before DDL
CatalogPlugin cat = lookupCatalog(catalogName);
if (!(cat instanceof TableCatalog)) {
  throw new IllegalStateException("Catalog " + catalogName + " cannot host tables");
}

Type guard

boolean isTableCatalog(CatalogPlugin catalog) {
  return catalog instanceof TableCatalog;
}

Try / catch

try {
  SparkCatalog ops = (SparkCatalog) catalog;
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("not a TableCatalog")) {
    // route to a different catalog or surface a config hint
  }
}

Prevention

When it happens

Trigger: Referencing a table in a catalog that does not implement TableCatalog — e.g. pointing USE/CREATE TABLE at spark_catalog, a view catalog, or a function catalog via Spark3Util.catalogAndIdentifier/asTableCatalog paths.

Common situations: Configuring spark.sql.defaultCatalog to a non-table catalog; writing CREATE TABLE ... USING iceberg with the table name resolving to a legacy session catalog; typos in catalog names that fall back to spark_catalog.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java:862

              try {
                return catalogManager.catalog(catalogName);
              } catch (Exception e) {
                LOG.warn("Failed to load catalog: {}", catalogName, e);
                return null;
              }
            },
            Identifier::of,
            defaultCatalog,
            currentNamespace);
    return new CatalogAndIdentifier(catalogIdentifier);
  }

  private static TableCatalog asTableCatalog(CatalogPlugin catalog) {
    if (catalog instanceof TableCatalog) {
      return (TableCatalog) catalog;
    }

    throw new IllegalArgumentException(
        String.format(
            "Cannot use catalog %s(%s): not a TableCatalog",
            catalog.name(), catalog.getClass().getName()));
  }

  /** This mimics a class inside of Spark which is private inside of LookupCatalog. */
  public static class CatalogAndIdentifier {
    private final CatalogPlugin catalog;
    private final Identifier identifier;

    public CatalogAndIdentifier(CatalogPlugin catalog, Identifier identifier) {
      this.catalog = catalog;
      this.identifier = identifier;
    }

    public CatalogAndIdentifier(Pair<CatalogPlugin, Identifier> identifier) {
      this.catalog = identifier.first();
      this.identifier = identifier.second();

View on GitHub (pinned to 86d9c8fc54)