apache/seatunnel · error · CatalogException

Database not empty, can't drop it.

Error message

Database %s not empty, can't drop it.

What it means

HudiCatalog.dropDatabase() refuses to drop a database (namespace on the DFS) that still contains tables. Before deleting the database directory it calls listTables(); if any table exists it aborts with this CatalogException to prevent silent data loss. You must drop or remove all tables in the database first.

Solutions

  1. List and drop every table in the database before calling dropDatabase (e.g. for each table in catalog.listTables(db) call catalog.dropTable(tablePath)).
  2. If the tables are not needed, manually remove the leftover directories on the underlying DFS (HDFS/S3) so listTables returns empty.
  3. If the database is intentionally expected empty but is not, verify the warehouse/tableParentDfsPath configuration is not pointing at the wrong location.

Example fix

// before
catalog.dropDatabase(tablePath);

// after
for (String table : catalog.listTables(tablePath.getDatabaseName())) {
    catalog.dropTable(TablePath.of(tablePath.getDatabaseName(), table));
}
catalog.dropDatabase(tablePath);
Defensive patterns

Strategy: validation

Validate before calling

if (!catalog.listTables(tablePath.getDatabaseName()).isEmpty()) {
    throw new IllegalStateException("Database not empty: " + tablePath.getDatabaseName());
}
catalog.dropDatabase(tablePath);

Prevention

When it happens

Trigger: Calling catalog.dropDatabase(tablePath) when listTables(databaseName) returns a non-empty list, i.e. there are still Hudi tables under the database directory on the filesystem.

Common situations: Automation scripts dropping databases without enumerating tables first; drop cascades executed while stale/undeleted Hudi tables remain on DFS; users assuming dropDatabase is recursive like SQL DROP ... CASCADE.

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/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/03d726d975028309. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-hudi/src/main/java/org/apache/seatunnel/connectors/seatunnel/hudi/catalog/HudiCatalog.java:310

                    e);
        }
    }

    @Override
    public void dropDatabase(TablePath tablePath, boolean ignoreIfNotExists)
            throws DatabaseNotExistException, CatalogException {
        // do nothing
        if (!databaseExists(tablePath.getDatabaseName())) {
            if (ignoreIfNotExists) {
                return;
            } else {
                throw new DatabaseNotExistException(catalogName, tablePath.getDatabaseName());
            }
        }

        List<String> tables = listTables(tablePath.getDatabaseName());
        if (!tables.isEmpty()) {
            throw new CatalogException(
                    String.format(
                            "Database %s not empty, can't drop it.", tablePath.getDatabaseName()));
        }

        Path dbPath = new Path(tableParentDfsPath, tablePath.getDatabaseName());
        try {
            fs.delete(dbPath, true);
        } catch (IOException e) {
            throw new CatalogException(
                    String.format("Dropping database %s exception.", tablePath.getDatabaseName()),
                    e);
        }
    }

    private TableSchema convertSchema(
            TableSchema.Builder tableSchemaBuilder, HoodieTableConfig tableConfig) {
        if (tableConfig.getTableCreateSchema().isPresent()) {
            Schema schema = tableConfig.getTableCreateSchema().get();

View on GitHub (pinned to cf67b549a7)