{"record":{"id":"39dac60326011297","repo":"apache/superset","slug":"a-soft-deleted-dataset-uuid-uuid-s-already-ref-39dac6","errorCode":null,"errorMessage":"A soft-deleted dataset (uuid %(uuid)s) already references this table. Restore it via POST /api/v1/dataset/%(uuid)s/restore before creating a new dataset over this table, or use a different table name.","messagePattern":"A soft-deleted dataset \\(uuid (.+?)\\) already references this table\\. Restore it via POST /api/v1/dataset/(.+?)/restore before creating a new dataset over this table, or use a different table name\\.","errorType":"validation","errorClass":"DatasetSoftDeletedTwinExistsError","httpStatus":422,"severity":"error","filePath":"superset/commands/dataset/create.py","lineNumber":85,"sourceCode":"            exceptions.append(DatabaseNotFoundValidationError())\n        self._properties[\"database\"] = database\n\n        # Validate uniqueness\n        if database:\n            if not catalog:\n                catalog = self._properties[\"catalog\"] = database.get_default_catalog()\n\n            table = Table(table_name, schema, catalog)\n\n            if not DatasetDAO.validate_uniqueness(database, table):\n                # Distinguish the hidden-twin case: uniqueness fails while\n                # the caller's dataset list looks empty. Raise the targeted\n                # 422 (naming the twin's uuid and the restore endpoint)\n                # instead of the opaque \"already exists\".\n                if soft_twin := DatasetDAO.find_soft_deleted_logical_duplicate(\n                    database, table\n                ):\n                    raise DatasetSoftDeletedTwinExistsError(str(soft_twin.uuid))\n                exceptions.append(DatasetExistsValidationError(table))\n\n        # Validate table exists on dataset if sql is not provided\n        # This should be validated when the dataset is physical\n        if (\n            database\n            and not sql\n            and not DatasetDAO.validate_table_exists(database, table)\n        ):\n            exceptions.append(TableNotFoundValidationError(table))\n\n        if sql:\n            try:\n                security_manager.raise_for_access(\n                    database=database,\n                    sql=sql,\n                    catalog=catalog,\n                    schema=schema,","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/dataset/create.py#L67-L103","documentation":"DatasetSoftDeletedTwinExistsError (HTTP 422) is raised by the dataset create command when uniqueness validation fails and DatasetDAO.find_soft_deleted_logical_duplicate finds a soft-deleted dataset referencing the same physical table (database/catalog/schema/table). The message names the twin's uuid and points at POST /api/v1/dataset/<uuid>/restore. It exists to disambiguate the confusing case where the dataset list 'looks empty' (soft-deleted rows are hidden) but the create still collides.","triggerScenarios":"POST /api/v1/dataset/ for a table whose dataset was previously soft-deleted (UI delete keeps the row with deleted_at set); recreating a dataset over a table that a deleted dashboard/dataset import claimed; the same physical table targeted after a delete-then-recreate cycle.","commonSituations":"Teams deleting a dataset to 'recreate it fresh' and hitting an invisible collision; soft-deleted rows accumulating after many experiments; restores attempted while a duplicate still exists.","solutions":["Restore the twin using the uuid from the message: POST /api/v1/dataset/<uuid>/restore — this makes the original dataset active again.","If you truly want a brand-new dataset, hard-delete the soft-deleted row (admin/CLI purge) or create the dataset over a different table name.","Do not retry the same create — the collision is deterministic until the twin is restored or purged."],"exampleFix":"# before\nPOST /api/v1/dataset/ {\"database\": 1, \"table_name\": \"sales\"}\n# -> 422 soft-deleted twin (uuid abc-...) exists\n\n# after\ncurl -X POST /api/v1/dataset/abc-.../restore\n# then edit the restored dataset instead of creating a new one","handlingStrategy":"fallback","validationCode":"# Detect a soft-deleted twin before creating\nfrom superset.daos.dataset import DatasetDAO\nfrom superset.connectors.sqla.models import Table\n\ndef soft_twin_uuid(database, table_name: str, schema=None, catalog=None):\n    twin = DatasetDAO.find_soft_deleted_logical_duplicate(\n        database, Table(table_name, schema, catalog)\n    )\n    return str(twin.uuid) if twin else None","typeGuard":null,"tryCatchPattern":"from superset.commands.dataset.exceptions import DatasetSoftDeletedTwinExistsError\nimport re\ntry:\n    CreateDatasetCommand(properties).run()\nexcept DatasetSoftDeletedTwinExistsError as ex:\n    uuid = re.search(\n        r\"uuid ([0-9a-f-]{36})\", str(ex)\n    ).group(1)\n    restore_dataset(uuid)  # fallback path: restore the twin instead of creating","preventionTips":["Prefer restoring (POST /api/v1/dataset/<uuid>/restore) over delete-and-recreate cycles.","When writing delete-then-create automation, hard-purge soft-deleted datasets or check find_soft_deleted_logical_duplicate first.","Teach users that UI delete is soft: the physical table claim survives."],"tags":["dataset","soft-delete","uniqueness","restore","flask-api"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}