apache/iceberg · error · NamespaceNotEmptyException
Cannot drop namespace %s because it still contains Iceberg t
Error message
Cannot drop namespace %s because it still contains Iceberg tables
What it means
GlueCatalog.dropNamespace throws NamespaceNotEmptyException when Glue's GetTables for the database returns at least one table whose parameters identify it as an Iceberg table. Iceberg refuses to drop a namespace that still contains Iceberg tables to prevent silent data loss.
Source
Thrown at aws/src/main/java/org/apache/iceberg/aws/glue/GlueCatalog.java:571
}
@Override
public boolean dropNamespace(Namespace namespace) throws NamespaceNotEmptyException {
namespaceExists(namespace);
GetTablesResponse response =
glue.getTables(
GetTablesRequest.builder()
.catalogId(awsProperties.glueCatalogId())
.databaseName(
IcebergToGlueConverter.toDatabaseName(
namespace, awsProperties.glueCatalogSkipNameValidation()))
.build());
if (response.hasTableList() && !response.tableList().isEmpty()) {
Table table = response.tableList().get(0);
if (isGlueIcebergTable(table)) {
throw new NamespaceNotEmptyException(
"Cannot drop namespace %s because it still contains Iceberg tables", namespace);
} else {
throw new NamespaceNotEmptyException(
"Cannot drop namespace %s because it still contains non-Iceberg tables", namespace);
}
}
glue.deleteDatabase(
DeleteDatabaseRequest.builder()
.catalogId(awsProperties.glueCatalogId())
.name(
IcebergToGlueConverter.toDatabaseName(
namespace, awsProperties.glueCatalogSkipNameValidation()))
.build());
LOG.info("Dropped namespace: {}", namespace);
// Always successful, otherwise exception is thrown
return true;
}View on GitHub (pinned to 86d9c8fc54)
Solutions
- Drop all Iceberg tables first: iterate catalog.listTables(ns) and call dropTable on each, then drop the namespace.
- Use dropTable(table, true) purge carefully only if the underlying data should also be deleted.
- If tables were already removed from Iceberg but stale entries remain in Glue, delete the orphan Glue table entries via the AWS console/API.
- Confirm you are dropping the intended database — the non-empty check may be catching a live production database.
Example fix
// before
catalog.dropNamespace(Namespace.of("staging"));
// after
Namespace ns = Namespace.of("staging");
for (TableIdentifier t : catalog.listTables(ns)) {
catalog.dropTable(t);
}
catalog.dropNamespace(ns); Defensive patterns
Strategy: validation
Validate before calling
Namespace ns = Namespace.of("staging");
if (!catalog.listTables(ns).isEmpty()) {
throw new IllegalStateException("Namespace " + ns + " still has tables; drop them first");
} Try / catch
try {
catalog.dropNamespace(ns);
} catch (NamespaceNotEmptyException e) {
catalog.listTables(ns).forEach(catalog::dropTable);
catalog.dropNamespace(ns);
} Prevention
- Enumerate and drop all tables before dropping a namespace
- Run teardown scripts that empty namespaces in order: tables then namespaces
- Use dedicated databases per pipeline so cleanup scope is obvious
When it happens
Trigger: Calling catalog.dropNamespace(ns) while the Glue database still contains Iceberg tables registered with metadata_location parameters.
Common situations: Cleanup scripts dropping databases without listing tables first; partial pipeline teardowns that deleted some but not all tables; forgetting that views/tables created by other engines in the same database block the drop.
Related errors
- Cannot drop namespace %s because it still contains non-Icebe
- Cannot create namespace %s because it already exists in Glue
- Glue does not support nested namespace, cannot list namespac
- invalid input for namespace %s, error message: %s
- fail to find Glue database for namespace %s, error message:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/4193a9503962bc27.
Report an issue: GitHub.