apache/iceberg · error · NoSuchTableException

Failed to load table %s from catalog %s: dropped by another

Error message

Failed to load table %s from catalog %s: dropped by another process

What it means

A NoSuchTableException signalling the table's metadata row disappeared from the JDBC catalog between operations. doRefresh() found an empty result but a metadata location was previously cached, meaning the table was deleted by another process. This prevents operations against a stale table reference.

Source

Thrown at core/src/main/java/org/apache/iceberg/jdbc/JdbcTableOperations.java:85

  @Override
  public void doRefresh() {
    Map<String, String> table;

    try {
      table = JdbcUtil.loadTable(schemaVersion, connections, catalogName, tableIdentifier);
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      throw new UncheckedInterruptedException(e, "Interrupted during refresh");
    } catch (SQLException e) {
      // SQL exception happened when getting table from catalog
      throw new UncheckedSQLException(
          e, "Failed to get table %s from catalog %s", tableIdentifier, catalogName);
    }

    if (table.isEmpty()) {
      if (currentMetadataLocation() != null) {
        throw new NoSuchTableException(
            "Failed to load table %s from catalog %s: dropped by another process",
            tableIdentifier, catalogName);
      } else {
        this.disableRefresh();
        return;
      }
    }

    String newMetadataLocation = table.get(METADATA_LOCATION_PROP);
    Preconditions.checkState(
        newMetadataLocation != null,
        "Invalid table %s: metadata location is null",
        tableIdentifier);
    refreshFromMetadataLocation(newMetadataLocation);
  }

  @Override
  public void doCommit(TableMetadata base, TableMetadata metadata) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Re-open the table via the catalog instead of continuing with the stale reference.
  2. Coordinate table lifecycle across processes (don't drop tables under active writers).
  3. Use catalog-level DROP TABLE rather than deleting catalog rows manually.
  4. Add application logic to catch NoSuchTableException and handle table recreation.

Example fix

// before
Table table = catalog.loadTable(identifier);
table.refresh(); // may throw if dropped elsewhere
// after
try {
  table.refresh();
} catch (NoSuchTableException e) {
  table = catalog.loadTable(identifier); // reload or handle missing table
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check the table still exists before committing
if (!catalog.tableExists(identifier)) {
  throw new IllegalStateException("Table " + identifier + " no longer exists in catalog");
}

Try / catch

try {
  table.refresh();
} catch (org.apache.iceberg.exceptions.NoSuchTableException e) {
  // table dropped by another process: stop writes, reload or recreate
  table = catalog.tableExists(identifier) ? catalog.loadTable(identifier) : null;
}

Prevention

When it happens

Trigger: doRefresh() calls JdbcUtil.loadTable and gets an empty map while currentMetadataLocation() != null — i.e., the cached table was dropped externally.

Common situations: Two jobs/processes sharing a catalog where one drops the table the other is still writing to, manual DELETE from the catalog DB, DROP TABLE issued concurrently with commits.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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