apache/iceberg · error · NoSuchTableException

Table not found

Error message

Table not found: ${from}

What it means

Thrown by SparkCatalog.renameTable when the underlying Iceberg catalog reports that the source table does not exist. Spark translates the Iceberg NoSuchTableException into Spark's org.apache.spark.sql.catalyst.analysis.NoSuchTableException carrying the original identifier. It means the rename's source identifier resolved to nothing in the catalog.

Solutions

  1. Verify the source table exists with 'SHOW TABLES IN <catalog>.<namespace>' or catalog.tableExists before renaming
  2. Check the identifier is fully qualified (namespace + name) and not a path identifier (starting with an absolute location)
  3. Confirm you are connected to the same catalog/warehouse that contains the table (check spark.sql.catalog.<name>.warehouse / type)
  4. Recreate or re-register the table if it was dropped

Example fix

// before
spark.sql("ALTER TABLE prod.events RENAME TO prod.events_archive")
// after
if (!spark.catalog().tableExists("prod", "events")) {
  throw new IllegalStateException("Source table prod.events does not exist");
}
spark.sql("ALTER TABLE prod.events RENAME TO prod.events_archive")
Defensive patterns

Strategy: validation

Validate before calling

if (!spark.catalog().tableExists(fromNamespace, fromName)) {
  throw new IllegalArgumentException("Source table does not exist: " + from);
}
if (from instanceof PathIdentifier || to instanceof PathIdentifier) {
  throw new IllegalArgumentException("renameTable does not support path identifiers");
}

Type guard

boolean isRenameable(TableCatalog catalog, Identifier from, Identifier to) {
  return catalog.tableExists(from) && !catalog.tableExists(to);
}

Try / catch

try {
  catalog.renameTable(from, to);
} catch (org.apache.spark.sql.catalyst.analysis.NoSuchTableException e) {
  log.error("Rename failed, source table missing: {}", from, e);
  throw new IllegalStateException("Cannot rename missing table " + from, e);
}

Prevention

When it happens

Trigger: Calling ALTER TABLE ... RENAME TO or SparkCatalog.renameTable(from, to) where 'from' is not a table in the catalog: the table was dropped, the name is misspelled or wrongly qualified, or a path identifier (a table loaded by 'spark_catalog.<path>') is passed since path identifiers are rejected.

Common situations: Renaming a table in a different namespace than assumed (missing qualifier), using a session catalog that points at a different warehouse than where the table lives, typos in table names, or attempting to rename a path-based table.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:409

  }

  private boolean catalogDropTable(Identifier ident) {
    if (isPathIdentifier(ident)) {
      return tables.dropTable(((PathIdentifier) ident).location(), false /* don't purge data */);
    } else {
      return icebergCatalog.dropTable(buildIdentifier(ident), false /* don't purge data */);
    }
  }

  @Override
  public void renameTable(Identifier from, Identifier to)
      throws NoSuchTableException, TableAlreadyExistsException {
    try {
      checkNotPathIdentifier(from, "renameTable");
      checkNotPathIdentifier(to, "renameTable");
      icebergCatalog.renameTable(buildIdentifier(from), buildIdentifier(to));
    } catch (org.apache.iceberg.exceptions.NoSuchTableException e) {
      throw new NoSuchTableException(from);
    } catch (AlreadyExistsException e) {
      throw new TableAlreadyExistsException(to);
    }
  }

  @Override
  public void invalidateTable(Identifier ident) {
    if (!isPathIdentifier(ident)) {
      icebergCatalog.invalidateTable(buildIdentifier(ident));
    }
  }

  @Override
  public Identifier[] listTables(String[] namespace) {
    return icebergCatalog.listTables(Namespace.of(namespace)).stream()
        .map(ident -> Identifier.of(ident.namespace().levels(), ident.name()))
        .toArray(Identifier[]::new);
  }

View on GitHub (pinned to 86d9c8fc54)