apache/superset · error · DatasetLogicalDuplicateError
Dataset cannot be restored because another active dataset al
Error message
Dataset cannot be restored because another active dataset already references the same physical table (same database, catalog, schema, and table name). Delete the duplicate or rename the table before restoring.
What it means
DatasetLogicalDuplicateError is raised by DatasetRestoreCommand.validate() when DatasetDAO.has_active_logical_duplicate(model) is true — i.e. while this dataset was soft-deleted, another active dataset row claimed the same physical table (same database, catalog, schema, table_name). Because DB-level uniqueness enforcement is inconsistent across schema builds, the command refuses the restore to return a clean 422 instead of an IntegrityError or a silent twin dataset.
Source
Thrown at superset/commands/dataset/restore.py:59
than relying on the DB, which would either reject with an opaque
IntegrityError or — where no constraint applies — silently allow two
active datasets pointing at the same physical table.
"""
dao = DatasetDAO
not_found_exc = DatasetNotFoundError
forbidden_exc = DatasetForbiddenError
restore_failed_exc = DatasetRestoreFailedError
def validate(self) -> SqlaTable: # type: ignore[override]
model = super().validate()
# DB-level uniqueness enforcement is inconsistent across schema
# builds (see class docstring), so restoring must refuse here if
# another active dataset claimed the same physical table while this
# one was soft-deleted — a clean 422 instead of an IntegrityError
# or a silent twin.
if DatasetDAO.has_active_logical_duplicate(model):
raise DatasetLogicalDuplicateError()
return model
View on GitHub (pinned to f4587218dd)
Solutions
- Delete (or hard-delete/purge) the newer duplicate dataset that now references the same physical table, then restore the soft-deleted one.
- Or rename the physical table (or point the duplicate at a different catalog/schema) so the (database, catalog, schema, table_name) tuple no longer collides.
- If the duplicate itself is the keeper, simply purge the soft-deleted row instead of restoring it.
- After resolving, retry the restore; verify uniqueness by listing datasets filtered by table_name.
Example fix
# before PUT /api/v1/dataset/42/restore # 422 ... another active dataset already references the same physical table # after # 1) find the twin GET /api/v1/dataset?q=(r:1,table_name:eq:my_table) # 2) delete the active duplicate (say id 99) DELETE /api/v1/dataset/99 # 3) restore PUT /api/v1/dataset/42/restore
Defensive patterns
Strategy: validation
Validate before calling
from superset.daos.dataset import DatasetDAO
model = DatasetDAO.find_by_id(model_id)
if model is not None and DatasetDAO.has_active_logical_duplicate(model):
raise SystemExit("resolve duplicate active dataset before restore") Try / catch
try:
DatasetRestoreCommand(user, model_id).run()
except DatasetLogicalDuplicateError as ex:
# message names the collision; delete/rename the twin, then retry once Prevention
- After deleting a dataset you may re-create, purge the soft-deleted row instead of leaving it restorable.
- Before restore, query for active datasets on the same (db, catalog, schema, table).
- Adopt one owner process for re-creating datasets to avoid twins.
When it happens
Trigger: Restoring a soft-deleted dataset (PUT /api/v1/dataset/{id}/restore or trash-restore UI) after someone re-created a dataset pointing at the identical physical table in the meantime. Also when two environments' data was merged, or a duplicate was created before the uniqueness constraint existed.
Common situations: Delete-then-recreate workflows: user deleted a dataset, re-added the same table as a new dataset, then later tries to restore the original from the trash. Restoring old backups/snapshots into a database where the table is already mapped.
Related errors
- A soft-deleted dataset (uuid %(uuid)s) already references th
- Chart {existing.slice_name!r} (uuid {config['uuid']}) was de
- Dashboard was deleted and re-import requires can_write permi
- A dashboard already exists and user doesn't have permissions
- Dashboard cannot be restored via re-import because its slug
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/0386ef811cf87d7c.
Report an issue: GitHub.