apache/iceberg · error · NoSuchTableException

Invalid table identifier: %s

Error message

Invalid table identifier: %s

What it means

When loading a table whose identifier is not valid for the catalog (and not a valid metadata identifier), the catalog reports it as NoSuchTableException with 'Invalid table identifier'. It fires on the branch where the identifier itself cannot denote a table in this catalog, e.g. an empty/invalid name for the catalog's namespace handling.

Source

Thrown at core/src/main/java/org/apache/iceberg/BaseMetastoreCatalog.java:66

      TableOperations ops = newTableOps(identifier);
      if (ops.current() == null) {
        // the identifier may be valid for both tables and metadata tables
        if (isValidMetadataIdentifier(identifier)) {
          result = loadMetadataTable(identifier);

        } else {
          throw new NoSuchTableException("Table does not exist: %s", identifier);
        }

      } else {
        result = new BaseTable(ops, fullTableName(name(), identifier), metricsReporter());
      }

    } else if (isValidMetadataIdentifier(identifier)) {
      result = loadMetadataTable(identifier);

    } else {
      throw new NoSuchTableException("Invalid table identifier: %s", identifier);
    }

    LOG.info("Table loaded by catalog: {}", result);
    return result;
  }

  @Override
  public Table registerTable(TableIdentifier identifier, String metadataFileLocation) {
    Preconditions.checkArgument(
        identifier != null && isValidIdentifier(identifier), "Invalid identifier: %s", identifier);
    Preconditions.checkArgument(
        metadataFileLocation != null && !metadataFileLocation.isEmpty(),
        "Cannot register an empty metadata file location as a table");

    // Throw an exception if this table already exists in the catalog.
    if (tableExists(identifier)) {
      throw new AlreadyExistsException("Table already exists: %s", identifier);
    }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Validate the TableIdentifier (non-empty namespace levels and name) before calling loadTable
  2. Ensure the namespace depth matches the catalog's expected hierarchy
  3. Use the correct catalog instance for the namespace layout

Example fix

// before
TableIdentifier bad = TableIdentifier.of(namespace); // name missing
Table t = catalog.loadTable(bad);
// after
ValidationException.check(!name.isEmpty(), "Table name required");
TableIdentifier ident = TableIdentifier.of(namespace, name);
Table t = catalog.loadTable(ident);
Defensive patterns

Strategy: validation

Validate before calling

ValidationException.check(identifier != null && !identifier.name().isEmpty() && identifier.namespace().levels().length > 0, "Invalid identifier: " + identifier);

Type guard

boolean isValid(TableIdentifier id) { return id != null && !id.name().isEmpty() && id.namespace().levels().length > 0; }

Try / catch

try { return catalog.loadTable(ident); } catch (NoSuchTableException e) { throw new IllegalArgumentException("Bad table identifier: " + ident, e); }

Prevention

When it happens

Trigger: loadTable with an identifier whose name is invalid (e.g. empty name) or whose namespace cannot form a valid table identifier for this catalog, and which is not a metadata-table name.

Common situations: Programmatic identifier construction producing empty names; mixing catalogs with different namespace semantics (e.g. nested namespaces on a two-level Hive metastore).

Related errors


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