apache/iceberg · error · NamespaceNotEmptyException
Namespace %s is not empty. One or more tables exist.
Error message
Namespace %s is not empty. One or more tables exist.
What it means
dropNamespace converts Hive Metastore's InvalidOperationException into Iceberg's NamespaceNotEmptyException because the database still contains tables. Hive refuses to drop a non-empty database, and the catalog surfaces that as a typed exception.
Source
Thrown at hive-metastore/src/main/java/org/apache/iceberg/hive/HiveCatalog.java:613
return false;
}
try {
clients.run(
client -> {
client.dropDatabase(
namespace.level(0),
false /* deleteData */,
false /* ignoreUnknownDb */,
false /* cascade */);
return null;
});
LOG.info("Dropped namespace: {}", namespace);
return true;
} catch (InvalidOperationException e) {
throw new NamespaceNotEmptyException(
e, "Namespace %s is not empty. One or more tables exist.", namespace);
} catch (NoSuchObjectException e) {
return false;
} catch (TException e) {
throw new RuntimeException("Failed to drop namespace " + namespace + " in Hive Metastore", e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(
"Interrupted in call to drop dropDatabase(name) " + namespace + " in Hive Metastore", e);
}
}
@Override
public boolean setProperties(Namespace namespace, Map<String, String> properties) {
Preconditions.checkArgument(View on GitHub (pinned to 86d9c8fc54)
Solutions
- Drop all tables first: iterate catalog.listTables(namespace) and drop each before dropping the namespace
- Use dropNamespace with purge/cascade semantics where supported, or run 'DROP DATABASE ... CASCADE' out-of-band if you accept deleting non-Iceberg objects
- Verify emptiness with listTables before dropping
Example fix
// before
catalog.dropNamespace(Namespace.of("legacy"), false);
// after
Namespace ns = Namespace.of("legacy");
for (TableIdentifier t : catalog.listTables(ns)) {
catalog.dropTable(t);
}
catalog.dropNamespace(ns, false); Defensive patterns
Strategy: validation
Validate before calling
Namespace ns = Namespace.of("legacy");
if (!catalog.listTables(ns).isEmpty()) {
throw new IllegalStateException("Namespace " + ns + " still has tables");
} Try / catch
try {
catalog.dropNamespace(ns, false);
} catch (NamespaceNotEmptyException e) {
catalog.listTables(ns).forEach(t -> catalog.dropTable(t));
catalog.dropNamespace(ns, false);
} Prevention
- Drop all tables before dropping the namespace
- Remember non-Iceberg tables in the same Hive DB also block the drop
- Check for views as well as tables
When it happens
Trigger: catalog.dropNamespace(Namespace.of("db"), false) when one or more tables/views still exist in the Hive database 'db'.
Common situations: Dropping a database before cleaning up tables; hidden tables registered via other engines (e.g. non-Iceberg tables) keeping the database non-empty; stale metadata listing omitted tables.
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
- Cannot drop namespace %s because it still contains Iceberg t
- Namespace %s is not empty.
- Cannot drop namespace %s because it still contains non-Icebe
- %s is not empty: %s
- Namespace %s is not empty. Contains %d child namespace(s).
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/300479e192adfa3c.
Report an issue: GitHub.