apache/superset · error · ImportFailedError

Dataset {existing.table_name!r} (uuid {config['uuid']}) was

Error message

Dataset {existing.table_name!r} (uuid {config['uuid']}) was deleted and re-import requires can_write permission to restore it

What it means

During v1 dataset import, when the uploaded UUID matches an existing soft-deleted (deleted_at set) dataset and the caller lacks can_write (dataset write permission), ImportFailedError is raised instead of silently returning the deleted row. The guard exists because returning the soft-deleted row would let the importer reattach charts/dashboards to a deleted dataset and produce broken artifacts.

Source

Thrown at superset/commands/dataset/importers/v1/utils.py:261

    # overwrite branches below are intentionally skipped because the caller has
    # already established trust at the command level.
    user = get_user()
    # Tracks whether we entered the soft-deleted mutation path so the
    # downstream `sync` decision (below) can reflect that an
    # implicit-restore re-import is a clean replacement, not a merge.
    is_soft_deleted_match = False

    if existing := find_existing_for_import(SqlaTable, config["uuid"]):
        if existing.deleted_at is not None:
            # RESTORE path — re-importing a soft-deleted UUID is an implicit
            # restore-with-update, a distinct operation from overwriting an
            # alive row, so it is handled in its own branch.
            if not can_write:
                # Case B: don't silently return a soft-deleted row to a caller
                # without write permission — that would let the importer
                # reattach charts/dashboards to a deleted dataset and produce
                # broken charts.
                raise ImportFailedError(
                    f"Dataset {existing.table_name!r} (uuid {config['uuid']}) "
                    "was deleted and re-import requires can_write permission "
                    "to restore it"
                )
            # ``user`` is None on background / example-loader paths; combined
            # with ``can_write`` (typically from ``ignore_permissions=True``)
            # the editorship check is intentionally skipped because the caller
            # already established trust.
            if user and (
                not security_manager.is_editor(existing)
                and not security_manager.is_admin()
            ):
                raise ImportFailedError(
                    f"Dataset {existing.table_name!r} (uuid {config['uuid']}) "
                    "already exists and user doesn't have permissions to "
                    "restore it"
                )
            # Before clearing ``deleted_at``, refuse if another active dataset

View on GitHub (pinned to f4587218dd)

Solutions

  1. Grant the importing user/role the can_write dataset permission (or the can_import permission set) and retry — the restore path then runs with proper editorship checks
  2. Have an admin restore the soft-deleted dataset first, then import
  3. Remove the dataset from the bundle if the restore is not intended
Defensive patterns

Strategy: try-catch

Validate before calling

from superset.daos.dataset import DatasetDAO
from superset.models.slice import Slice  # not needed; illustration of pre-check
# pre-check: does the uuid match a soft-deleted row, and can we write?
existing = find_existing_for_import(SqlaTable, config['uuid'])
if existing is not None and existing.deleted_at is not None:
    assert current_user_has_dataset_write(), 're-import of a deleted dataset requires can_write'

Try / catch

from superset.commands.exceptions import ImportFailedError
try:
    import_dataset(config, overwrite=True)
except ImportFailedError as ex:
    if 'requires can_write permission to restore it' in str(ex):
        # elevate/grant permission or drop the dataset from the bundle; do not retry unchanged
        ...

Prevention

When it happens

Trigger: Importing a bundle whose dataset UUID matches a dataset in the trash, via a REST import by a user without can_write permission on datasets (and not ignore_permissions).

Common situations: A user re-imports an old export after the dataset was soft-deleted; batch import scripts running under a read-mostly role; importing a dashboard bundle that embeds the deleted dataset's UUID.

Related errors


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