apache/iceberg · error · NoSuchTableException

Invalid identifier: %s

Error message

Invalid identifier: %s

What it means

HadoopCatalog.dropTable throws NoSuchTableException when the given TableIdentifier fails isValidIdentifier. In this catalog, isValidIdentifier effectively always returns true (HadoopCatalog.java:224), so in practice this error is nearly unreachable via dropTable directly; it is a defensive guard meant for subclasses with identifier constraints.

Source

Thrown at core/src/main/java/org/apache/iceberg/hadoop/HadoopCatalog.java:251

  @Override
  protected String defaultWarehouseLocation(TableIdentifier tableIdentifier) {
    String tableName = tableIdentifier.name();
    StringBuilder sb = new StringBuilder();

    sb.append(warehouseLocation).append('/');
    for (String level : tableIdentifier.namespace().levels()) {
      sb.append(level).append('/');
    }
    sb.append(tableName);

    return sb.toString();
  }

  @Override
  public boolean dropTable(TableIdentifier identifier, boolean purge) {
    if (!isValidIdentifier(identifier)) {
      throw new NoSuchTableException("Invalid identifier: %s", identifier);
    }

    Path tablePath = new Path(defaultWarehouseLocation(identifier));
    TableOperations ops = newTableOps(identifier);
    TableMetadata lastMetadata = ops.current();
    try {
      if (lastMetadata == null) {
        LOG.debug("Not an iceberg table: {}", identifier);
        return false;
      } else {
        if (purge) {
          // Since the data files and the metadata files may store in different locations,
          // so it has to call dropTableData to force delete the data file.
          CatalogUtil.dropTableData(ops.io(), lastMetadata);
        }
        return fs.delete(tablePath, true /* recursive */);
      }
    } catch (IOException e) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Validate the TableIdentifier (non-empty name, no path-separator characters like '/' or '..') before calling dropTable.
  2. Check the subclass implementation of isValidIdentifier to learn its exact rules.
  3. Confirm you are calling dropTable on the intended catalog instance, not one with stricter identifier validation.
  4. Handle NoSuchTableException and surface a corrected identifier to the caller.

Example fix

// before: blind drop
catalog.dropTable(TableIdentifier.of(ns, userInput), false);

// after: validate first
if (userInput.contains("/") || userInput.isEmpty()) {
  throw new IllegalArgumentException("Invalid table name: " + userInput);
}
catalog.dropTable(TableIdentifier.of(ns, userInput), false);
Defensive patterns

Strategy: validation

Validate before calling

boolean valid = ident != null && !ident.name().isEmpty() && !ident.name().contains("/");
if (!valid) throw new IllegalArgumentException("Invalid identifier: " + ident);

Try / catch

try { catalog.dropTable(ident, false); } catch (NoSuchTableException e) { // surface corrected identifier to caller }

Prevention

When it happens

Trigger: Calling catalog.dropTable(identifier, purge) with an identifier that a subclass's isValidIdentifier rejects (e.g. identifiers with unsupported characters, reserved names, or wrong namespace shape when the base method is overridden).

Common situations: Using a subclass of HadoopCatalog with stricter identifier rules, passing identifiers built from unvalidated user input, or identifiers containing path-hostile characters like '/', '..', or empty segments.

Related errors


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