apache/iceberg · error · NamespaceNotEmptyException

Namespace is not empty. Contains table(s).

Error message

Namespace %s is not empty. Contains %d table(s).

What it means

dropNamespace throws NamespaceNotEmptyException when the namespace still contains tables. Tables under the namespace block its deletion even if child namespaces were already removed. The message reports the number of blocking tables.

Solutions

  1. Drop all tables via catalog.dropTable(identifier) before dropping the namespace
  2. Use catalog.listTables(ns) to enumerate and handle each table (drop or rename out)
  3. Catch NamespaceNotEmptyException and inspect listTables to report leftover tables to the operator

Example fix

// before
catalog.dropNamespace(ns);
// after
for (TableIdentifier t : catalog.listTables(ns)) {
  catalog.dropTable(t);
}
catalog.dropNamespace(ns);
Defensive patterns

Strategy: validation

Validate before calling

if (!catalog.listTables(ns).isEmpty()) { throw new IllegalStateException("namespace has tables"); }

Type guard

boolean dropSafe = catalog.listTables(ns).isEmpty() && catalog.listViews(ns).isEmpty();

Try / catch

try { catalog.dropNamespace(ns); } catch (NamespaceNotEmptyException e) { /* enumerate listTables, drop each, retry */ }

Prevention

When it happens

Trigger: Calling catalog.dropNamespace(ns) while listTables(ns) returns identifiers and the namespace's child-namespace check has already passed.

Common situations: Cleanup jobs that drop namespaces without purging tables first; abandoned tables from failed pipelines; users expecting dropNamespace to cascade (it does not).

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java:555

    }
  }

  @Override
  public boolean dropNamespace(Namespace namespace) throws NamespaceNotEmptyException {
    if (!namespaceExists(namespace)) {
      return false;
    }

    List<Namespace> childNamespaces = listNamespaces(namespace);
    if (childNamespaces != null && !childNamespaces.isEmpty()) {
      throw new NamespaceNotEmptyException(
          "Namespace %s is not empty. Contains %d child namespace(s).",
          namespace, childNamespaces.size());
    }

    List<TableIdentifier> tableIdentifiers = listTables(namespace);
    if (tableIdentifiers != null && !tableIdentifiers.isEmpty()) {
      throw new NamespaceNotEmptyException(
          "Namespace %s is not empty. Contains %d table(s).", namespace, tableIdentifiers.size());
    }

    if (schemaVersion != JdbcUtil.SchemaVersion.V0) {
      List<TableIdentifier> viewIdentifiers = listViews(namespace);
      if (viewIdentifiers != null && !viewIdentifiers.isEmpty()) {
        throw new NamespaceNotEmptyException(
            "Namespace %s is not empty. Contains %d view(s).", namespace, viewIdentifiers.size());
      }
    }

    int deletedRows =
        execute(
            JdbcUtil.DELETE_ALL_NAMESPACE_PROPERTIES_SQL,
            catalogName,
            JdbcUtil.namespaceToString(namespace));

    return deletedRows > 0;

View on GitHub (pinned to 86d9c8fc54)