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

  1. Drop or purge all tables in the database first (DROP TABLE each, or purge)
  2. Use DROP DATABASE ... CASCADE so the call passes cascade semantics (FlinkCatalog translates this so the Iceberg dropNamespace purge succeeds)
  3. Check listTables(database) to see what remains blocking the drop
  4. 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

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


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