apache/superset · error · DatabaseDeleteFailedReportsExistError

There are associated alerts or reports: %(report_names)s

Error message

There are associated alerts or reports: %(report_names)s

What it means

DatabaseDeleteFailedReportsExistError raised in DeleteDatabaseCommand.validate (delete.py:59) when ReportScheduleDAO.find_by_database_id(self._model_id) returns rows. Superset refuses to hard-delete a database that alert/report schedules depend on; the message interpolates the offending schedule names via the _() gettext template 'There are associated alerts or reports: %(report_names)s'.

Source

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

        self._model_id = model_id
        self._model: Optional[Database] = None

    @transaction(on_error=partial(on_error, reraise=DatabaseDeleteFailedError))
    def run(self) -> None:
        self.validate()
        assert self._model
        DatabaseDAO.delete([self._model])

    def validate(self) -> None:
        # Validate/populate model exists
        self._model = DatabaseDAO.find_by_id(self._model_id)
        if not self._model:
            raise DatabaseNotFoundError()
        # Check there are no associated ReportSchedules

        if reports := ReportScheduleDAO.find_by_database_id(self._model_id):
            report_names = [report.name for report in reports]
            raise DatabaseDeleteFailedReportsExistError(
                _(
                    "There are associated alerts or reports: %(report_names)s",
                    report_names=",".join(report_names),
                )
            )
        # Check if there are datasets for this database. ``self._model.tables``
        # would now hide soft-deleted datasets (``SqlaTable`` inherits
        # ``SoftDeleteMixin``, so the relationship lazy-load applies the
        # visibility filter), letting a database whose datasets are all
        # soft-deleted look empty and be hard-deleted while ``tables.database_id``
        # rows still reference it. Count with the visibility filter bypassed so
        # soft-deleted datasets still block the delete.
        from superset.connectors.sqla.models import (  # pylint: disable=import-outside-toplevel
            SqlaTable,
        )
        from superset.extensions import (  # pylint: disable=import-outside-toplevel
            db,
        )

View on GitHub (pinned to f4587218dd)

Solutions

  1. The error message names the schedules — delete or re-point each one (DELETE /api/v1/report/<id> or change its target).
  2. Search all reports for dependencies before deleting a database: GET /api/v1/report/ and inspect targets.
  3. If the reports are obsolete, pause/delete them in bulk via the UI (Manage > Alerts & Reports).
  4. Retry the database delete once no schedule references it.
Defensive patterns

Strategy: validation

Validate before calling

from superset.daos.report import ReportScheduleDAO

def database_has_reports(model_id: int) -> bool:
    return ReportScheduleDAO.find_by_database_id(model_id) is not None

Try / catch

from superset.commands.database.exceptions import DatabaseDeleteFailedReportsExistError

try:
    DeleteDatabaseCommand(model_id).run()
except DatabaseDeleteFailedReportsExistError as ex:
    # ex.message lists the schedule names: delete or re-point them, then retry
    show_list(ex.message)

Prevention

When it happens

Trigger: DELETE /api/v1/database/<id> when at least one Alert or Report schedule targets a chart/dataset backed by this database.

Common situations: Legacy weekly report emails pointing at a database being decommissioned; alerts on datasets nobody remembered; deleting a database after migrating its datasets but not the schedules.

Related errors


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