apache/superset · error · DatabaseDeleteDatasetsExistFailedError

Cannot delete a database that has datasets attached

Error message

Cannot delete a database that has datasets attached

What it means

DatabaseDeleteDatasetsExistFailedError ('Cannot delete a database that has datasets attached') raised in DeleteDatabaseCommand.validate (delete.py:100) when the visibility-filter-bypassing count finds at least one LIVE (non-soft-deleted) SqlaTable row with database_id == self._model_id. The explicit EXISTS queries are there precisely because the ORM relationship would hide soft-deleted datasets; has_live being true means ordinary, visible datasets still reference the database.

Source

Thrown at superset/commands/database/delete.py:100

        with skip_visibility_filter(db.session, SqlaTable):
            has_live = db.session.query(
                db.session.query(SqlaTable.id)
                .filter(
                    SqlaTable.database_id == self._model_id,
                    SqlaTable.deleted_at.is_(None),
                )
                .exists()
            ).scalar()
            has_any = db.session.query(
                db.session.query(SqlaTable.id)
                .filter(SqlaTable.database_id == self._model_id)
                .exists()
            ).scalar()
        # Both cases block the delete (a soft-deleted dataset still FK-references
        # the database), but the message differs: with only hidden rows left the
        # operator's dataset list looks empty, so say so explicitly.
        if has_live:
            raise DatabaseDeleteDatasetsExistFailedError()
        if has_any:
            raise DatabaseDeleteSoftDeletedDatasetsExistFailedError()

View on GitHub (pinned to f4587218dd)

Solutions

  1. List the attached datasets (GET /api/v1/dataset/?q=(database_id:<id>)) and delete them (DELETE /api/v1/dataset/<pk>) or migrate them to another database.
  2. If the data is moving, duplicate datasets against the new database first, then delete the old ones.
  3. Retry the database delete only after the live dataset count is zero.
Defensive patterns

Strategy: validation

Validate before calling

from superset.models.sql_lab import Query  # placeholder
from superset.connectors.sqla.models import SqlaTable
from superset import db

def live_dataset_count(database_id: int) -> int:
    return (
        db.session.query(SqlaTable.id)
        .filter(SqlaTable.database_id == database_id)
        .count()
    )  # non-zero blocks the delete

Try / catch

from superset.commands.database.exceptions import DatabaseDeleteDatasetsExistFailedError

try:
    DeleteDatabaseCommand(model_id).run()
except DatabaseDeleteDatasetsExistFailedError:
    list_and_offer_migration(database_id)  # show live datasets, delete or re-point

Prevention

When it happens

Trigger: DELETE /api/v1/database/<id> while any dataset in the UI (Datasets list) still points at this database.

Common situations: Decommissioning a database without first migrating or deleting its datasets; datasets created implicitly by CSV uploads; forgetting virtual/saved datasets.

Related errors


AI-assisted analysis of apache/superset@f4587218dd (2026-08-14). Data as JSON: /api/errors/09d855b9f7824e38. Report an issue: GitHub.