apache/iceberg · error · IllegalArgumentException

Illegal table name:

Error message

Illegal table name:

What it means

FlinkCatalog.toIdentifier converts a Flink ObjectPath into an Iceberg TableIdentifier relative to the catalog's base namespace. If the resulting name cannot be represented — e.g. the table name has more levels than expected or the metadata-table mapping fails — it throws IllegalArgumentException 'Illegal table name:'. It signals the requested name is not addressable through this catalog, not that the table is missing.

Source

Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/FlinkCatalog.java:166

    String[] namespace = new String[baseNamespace.levels().length + 1];
    System.arraycopy(baseNamespace.levels(), 0, namespace, 0, baseNamespace.levels().length);
    namespace[baseNamespace.levels().length] = newLevel;
    return Namespace.of(namespace);
  }

  TableIdentifier toIdentifier(ObjectPath path) {
    String objectName = path.getObjectName();
    List<String> tableName = Splitter.on('$').splitToList(objectName);

    if (tableName.size() == 1) {
      return TableIdentifier.of(
          appendLevel(baseNamespace, path.getDatabaseName()), path.getObjectName());
    } else if (tableName.size() == 2 && MetadataTableType.from(tableName.get(1)) != null) {
      return TableIdentifier.of(
          appendLevel(appendLevel(baseNamespace, path.getDatabaseName()), tableName.get(0)),
          tableName.get(1));
    } else {
      throw new IllegalArgumentException("Illegal table name:" + objectName);
    }
  }

  @Override
  public List<String> listDatabases() throws CatalogException {
    if (asNamespaceCatalog == null) {
      return Collections.singletonList(getDefaultDatabase());
    }

    return asNamespaceCatalog.listNamespaces(baseNamespace).stream()
        .map(n -> n.level(n.levels().length - 1))
        .collect(Collectors.toList());
  }

  @Override
  public CatalogDatabase getDatabase(String databaseName)
      throws DatabaseNotExistException, CatalogException {
    if (asNamespaceCatalog == null) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Use a two-part ObjectPath (database.object) matching the catalog's expected nesting; avoid extra levels.
  2. If targeting an Iceberg metadata table, use an exact supported suffix (e.g. 'tbl.history', 'tbl.snapshots').
  3. Print the full objectName being passed and correct the caller (SQL path, connector options) that built it.
  4. For deep namespaces, configure the Flink catalog's base namespace so remaining depth is exactly 2.

Example fix

// before
ObjectPath path = new ObjectPath("db", "a.b.c"); // too many levels
// after
ObjectPath path = new ObjectPath("db", "tbl"); // database.table
// or for metadata tables:
ObjectPath metaPath = new ObjectPath("db", "tbl.snapshots");
Defensive patterns

Strategy: validation

Validate before calling

// validate object path arity before calling catalog methods
static void checkPath(ObjectPath path) {
  String name = path.getObjectName();
  boolean isMetadataTable = name != null && MetadataTableType.from(name) != null;
  // plain table: objectName has no dot; metadata table: exactly one dot with valid suffix
  if (name.contains(".") && !isMetadataTable) {
    throw new IllegalArgumentException("unsupported table name: " + name);
  }
}

Try / catch

try {
  catalog.dropTable(path);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Illegal table name")) {
    throw new ValidationException("cannot address " + path + " through this catalog: " + e.getMessage(), e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling table/tableExists/dropTable/renameTable/createTableLoader with an ObjectPath whose name is neither a plain table nor a recognized 2-part metadata table form; nested or malformed identifiers (extra dots, wrong depth) passed from Flink SQL or the API.

Common situations: Referencing tables with unusual quoting in Flink SQL ('cat.db.db2.tbl' against a single-level catalog), typos in metadata-table suffixes, programmatic ObjectPath construction with the wrong arity.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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