apache/iceberg · error · NamespaceNotEmptyException

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

Error message

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

What it means

NamespaceNotEmptyException from InMemoryCatalog.dropNamespace: after checking child namespaces, the namespace still contains one or more tables, so it cannot be removed. The formatted message reports the namespace and the table count; drop or move the tables first.

Source

Thrown at core/src/main/java/org/apache/iceberg/inmemory/InMemoryCatalog.java:232

  }

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

      List<Namespace> childNamespaces = listNamespaces(namespace);
      if (!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.isEmpty()) {
        throw new NamespaceNotEmptyException(
            "Namespace %s is not empty. Contains %d table(s).", namespace, tableIdentifiers.size());
      }

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

      return namespaces.remove(namespace) != null;
    }
  }

  @Override
  public boolean setProperties(Namespace namespace, Map<String, String> properties)
      throws NoSuchNamespaceException {
    synchronized (this) {
      if (!namespaceExists(namespace)) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Drop all tables in the namespace first (listTables then dropTable for each), then retry dropNamespace
  2. Also drop any views if present, since the next check rejects views too
  3. Wrap the drop in a loop/retry if concurrent writers may add tables

Example fix

// before
catalog.dropNamespace(ns);
// after
catalog.listTables(ns).forEach(t -> catalog.dropTable(t, false));
catalog.listViews(ns).forEach(v -> catalog.dropView(v));
catalog.dropNamespace(ns);
Defensive patterns

Strategy: validation

Validate before calling

if (!catalog.listTables(ns).isEmpty()) throw new IllegalStateException("Namespace has tables: " + ns);

Try / catch

try { catalog.dropNamespace(ns); } catch (NamespaceNotEmptyException e) { /* drop children first */ }

Prevention

When it happens

Trigger: Calling catalog.dropNamespace(ns) after listTables(ns) returns one or more TableIdentifier entries.

Common situations: Cleaning up test namespaces without dropping tables first; migration scripts assuming drop cascades; parallel writers created tables after an isEmpty check.

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/2de9217317705332. Report an issue: GitHub.