{"record":{"id":"0386ef811cf87d7c","repo":"apache/superset","slug":"dataset-cannot-be-restored-because-another-active","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"exception","errorClass":"DatasetLogicalDuplicateError","httpStatus":422,"severity":"error","filePath":"superset/commands/dataset/restore.py","lineNumber":59,"sourceCode":"    than relying on the DB, which would either reject with an opaque\n    IntegrityError or — where no constraint applies — silently allow two\n    active datasets pointing at the same physical table.\n    \"\"\"\n\n    dao = DatasetDAO\n    not_found_exc = DatasetNotFoundError\n    forbidden_exc = DatasetForbiddenError\n    restore_failed_exc = DatasetRestoreFailedError\n\n    def validate(self) -> SqlaTable:  # type: ignore[override]\n        model = super().validate()\n        # DB-level uniqueness enforcement is inconsistent across schema\n        # builds (see class docstring), so restoring must refuse here if\n        # another active dataset claimed the same physical table while this\n        # one was soft-deleted — a clean 422 instead of an IntegrityError\n        # or a silent twin.\n        if DatasetDAO.has_active_logical_duplicate(model):\n            raise DatasetLogicalDuplicateError()\n        return model\n","sourceCodeStart":41,"sourceCodeEnd":61,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/dataset/restore.py#L41-L61","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nPUT /api/v1/dataset/42/restore\n# 422 ... another active dataset already references the same physical table\n\n# after\n# 1) find the twin\nGET /api/v1/dataset?q=(r:1,table_name:eq:my_table)\n# 2) delete the active duplicate (say id 99)\nDELETE /api/v1/dataset/99\n# 3) restore\nPUT /api/v1/dataset/42/restore","handlingStrategy":"validation","validationCode":"from superset.daos.dataset import DatasetDAO\n\nmodel = DatasetDAO.find_by_id(model_id)\nif model is not None and DatasetDAO.has_active_logical_duplicate(model):\n    raise SystemExit(\"resolve duplicate active dataset before restore\")","typeGuard":null,"tryCatchPattern":"try:\n    DatasetRestoreCommand(user, model_id).run()\nexcept DatasetLogicalDuplicateError as ex:\n    # message names the collision; delete/rename the twin, then retry once","preventionTips":["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."],"tags":["dataset","restore","duplicate","unique-constraint","soft-delete"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}