apache/iceberg · error · NamespaceNotEmptyException
Cannot delete non-empty namespace %s
Error message
Cannot delete non-empty namespace %s
What it means
DynamoDbCatalog.dropNamespace() refuses to drop a namespace that still contains tables, throwing NamespaceNotEmptyException with this message. Before deleting the namespace item it calls listTables(namespace); any result blocks the drop, protecting tables from being orphaned.
Source
Thrown at aws/src/main/java/org/apache/iceberg/aws/dynamodb/DynamoDbCatalog.java:284
.tableName(awsProperties.dynamoDbTableName())
.consistentRead(true)
.key(namespacePrimaryKey(namespace))
.build());
if (!response.hasItem()) {
throw new NoSuchNamespaceException("Cannot find namespace %s", namespace);
}
return response.item().entrySet().stream()
.filter(e -> isProperty(e.getKey()))
.collect(Collectors.toMap(e -> toPropertyKey(e.getKey()), e -> e.getValue().s()));
}
@Override
public boolean dropNamespace(Namespace namespace) throws NamespaceNotEmptyException {
validateNamespace(namespace);
if (!listTables(namespace).isEmpty()) {
throw new NamespaceNotEmptyException("Cannot delete non-empty namespace %s", namespace);
}
try {
dynamo.deleteItem(
DeleteItemRequest.builder()
.tableName(awsProperties.dynamoDbTableName())
.key(namespacePrimaryKey(namespace))
.conditionExpression("attribute_exists(" + COL_NAMESPACE + ")")
.build());
return true;
} catch (ConditionalCheckFailedException e) {
return false;
}
}
@Override
public boolean setProperties(Namespace namespace, Map<String, String> properties)
throws NoSuchNamespaceException {View on GitHub (pinned to 86d9c8fc54)
Solutions
- List and drop all tables in the namespace first: for (TableIdentifier t : catalog.listTables(namespace)) catalog.dropTable(t); then retry dropNamespace.
- If the rows are known orphans, remove the stale table items from the DynamoDB catalog table, then retry the drop.
- Catch org.apache.iceberg.exceptions.NamespaceNotEmptyException if the caller intentionally skips non-empty namespaces.
Example fix
// before
catalog.dropNamespace(Namespace.of("staging"));
// after
for (TableIdentifier t : catalog.listTables(Namespace.of("staging"))) {
catalog.dropTable(t);
}
catalog.dropNamespace(Namespace.of("staging")); Defensive patterns
Strategy: validation
Validate before calling
Namespace ns = Namespace.of("staging");
if (!catalog.listTables(ns).isEmpty()) {
throw new IllegalStateException("Refusing to drop non-empty namespace " + ns);
}
catalog.dropNamespace(ns); Try / catch
try {
catalog.dropNamespace(ns);
} catch (NamespaceNotEmptyException e) {
catalog.listTables(ns).forEach(t -> catalog.dropTable(t));
catalog.dropNamespace(ns);
} Prevention
- Always drain tables before dropping namespaces in teardown scripts
- Run orphan-row cleanup for the DynamoDB catalog table periodically
- Check nested namespace levels for tables sharing the partition key prefix
When it happens
Trigger: Calling catalog.dropNamespace(namespace) when listTables(namespace) returns at least one table registered under that namespace in the DynamoDB catalog table.
Common situations: Cleanup scripts that drop namespaces without dropping child tables first; partially failed teardown leaving orphaned table rows; nested namespaces where tables exist under a deeper level sharing the same partition key prefix.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Cannot find default warehouse location: namespace %s does no
- Cannot create namespace %s: already exists
- Cannot find namespace %s
- Cannot find table %s to drop
- Cannot rename table %s to %s: %s does not exist
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/9152f6189ab5efe7.
Report an issue: GitHub.