apache/iceberg · error · IllegalArgumentException

Illegal table name:

Error message

Illegal table name:

What it means

FlinkCatalog.toIdentifier converts a Flink ObjectPath (catalog.database.table) into an Iceberg TableIdentifier. After mapping namespace levels and any metadata-table suffix, the resulting table name has an unexpected number of parts, so the input object name is rejected as an illegal table name. The message ends with the offending objectName.

Source

Thrown at flink/v2.2/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 table name without extra dot-separated levels, or properly quote the identifier in Flink SQL
  2. If reading a metadata table, use an exact valid suffix: snapshots, history, files, manifests, refs, partitions, all_data_files, etc.
  3. Check the objectName does not embed database qualification when passed to toIdentifier
  4. Log/inspect the failing objectName in the message and correct the call site

Example fix

// before
catalog.dropTable(new ObjectPath(db, "mytable.snapshots.typo"));
// after
catalog.dropTable(new ObjectPath(db, "mytable.snapshots")); // valid metadata table name
Defensive patterns

Strategy: validation

Validate before calling

ObjectPath path = ...;
String name = path.getObjectName();
if (name.contains(".")) {
  String[] parts = name.split("\\.");
  if (parts.length > 2 || (parts.length == 2 && MetadataTableType.from(parts[1]) == null)) {
    throw new IllegalArgumentException("unsupported table name: " + name);
  }
}

Try / catch

try {
  catalog.table(objectPath);
} catch (IllegalArgumentException e) {
  LOG.error("bad table identifier: {}", objectPath.getObjectName());
  throw e;
}

Prevention

When it happens

Trigger: Calling table(), tableExists(), dropTable(), renameTable(), createIcebergTable(), or createTableLoader() with an ObjectPath whose object name resolves to more than two levels or an unrecognized second segment — e.g. names containing extra dots producing a 3+ element tableName list, or a second segment that is not a known MetadataTableType.

Common situations: Quoting/dotted identifiers in Flink SQL producing multi-level names; typo'd metadata table names (e.g. 'snapshotss' instead of 'snapshots'); passing fully-qualified names into APIs expecting a simple object name.

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