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

  1. List and drop all tables in the namespace first: for (TableIdentifier t : catalog.listTables(namespace)) catalog.dropTable(t); then retry dropNamespace.
  2. If the rows are known orphans, remove the stale table items from the DynamoDB catalog table, then retry the drop.
  3. 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

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/9152f6189ab5efe7. Report an issue: GitHub.