apache/iceberg · error · DatabaseNotEmptyException
DatabaseNotEmptyException
Error message
DatabaseNotEmptyException
What it means
FlinkCatalog.dropDatabase throws DatabaseNotEmptyException when the underlying Iceberg catalog raises NamespaceNotEmptyException, i.e. the namespace still contains tables (or views) and cannot be dropped while cascade=false. The namespace is NOT removed and its contents remain intact.
Source
Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/FlinkCatalog.java:263
}
return ret;
}
@Override
public void dropDatabase(String name, boolean ignoreIfNotExists, boolean cascade)
throws DatabaseNotExistException, DatabaseNotEmptyException, CatalogException {
if (asNamespaceCatalog != null) {
try {
boolean success = asNamespaceCatalog.dropNamespace(appendLevel(baseNamespace, name));
if (!success && !ignoreIfNotExists) {
throw new DatabaseNotExistException(getName(), name);
}
} catch (NoSuchNamespaceException e) {
if (!ignoreIfNotExists) {
throw new DatabaseNotExistException(getName(), name, e);
}
} catch (NamespaceNotEmptyException e) {
throw new DatabaseNotEmptyException(getName(), name, e);
}
} else {
if (!ignoreIfNotExists) {
throw new DatabaseNotExistException(getName(), name);
}
}
}
@Override
public void alterDatabase(String name, CatalogDatabase newDatabase, boolean ignoreIfNotExists)
throws DatabaseNotExistException, CatalogException {
if (asNamespaceCatalog != null) {
Namespace namespace = appendLevel(baseNamespace, name);
Map<String, String> updates = Maps.newHashMap();
Set<String> removals = Sets.newHashSet();
try {
Map<String, String> oldProperties = asNamespaceCatalog.loadNamespaceMetadata(namespace);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Drop or purge all tables in the database first (DROP TABLE each, or purge)
- Use DROP DATABASE ... CASCADE so the call passes cascade semantics (FlinkCatalog translates this so the Iceberg dropNamespace purge succeeds)
- Check listTables(database) to see what remains blocking the drop
- If tables are stale/orphaned, remove them via the Iceberg catalog directly before retrying
Example fix
// before
staging.executeSql("DROP DATABASE my_db");
// after
staging.executeSql("DROP DATABASE my_db CASCADE"); Defensive patterns
Strategy: validation
Validate before calling
boolean empty = catalog.listTables(dbName).isEmpty();
if (!empty) throw new IllegalStateException("Database " + dbName + " still contains tables"); Try / catch
try {
catalog.dropDatabase(name, false, false);
} catch (DatabaseNotEmptyException e) {
catalog.listTables(name).forEach(t -> catalog.dropTable(ObjectPath.fromString(name + "." + t), true));
catalog.dropDatabase(name, false, true);
} Prevention
- List tables before dropping a database
- Use CASCADE explicitly when recursive deletion is intended
- Never assume namespace drop is recursive in Iceberg
When it happens
Trigger: Calling dropDatabase(name, ignoreIfNotExists=false, cascade=false) — e.g. DROP DATABASE without CASCADE — on a namespace that still holds tables/views in the Iceberg catalog.
Common situations: Attempting to clean up a database that still has Iceberg tables; forgetting CASCADE in Flink SQL; assuming drop of the namespace recursively deletes contents when the wrapped catalog refuses.
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
- Can not alter the default database when the iceberg catalog
- TableNotExistException
- FunctionNotExistException
- Cannot delete non-empty namespace %s
- Illegal table name:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/08bd3e1ef1657853.
Report an issue: GitHub.