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
- Drop all tables in the namespace first (listTables then dropTable for each), then retry dropNamespace
- Also drop any views if present, since the next check rejects views too
- 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
- Always drop tables and views before dropNamespace
- Guard concurrent writers with locks or retries
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
- Namespace %s is not empty. Contains %d view(s).
- Namespace does not exist: %s
- Namespace already exists: %s
- Namespace %s is not empty.
- Cannot set namespace properties " + namespace + " : setPrope
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/2de9217317705332.
Report an issue: GitHub.