apache/superset · error · ImportFailedError
Dataset {existing.table_name!r} (uuid {config['uuid']}) matc
Error message
Dataset {existing.table_name!r} (uuid {config['uuid']}) matches more than one existing row, so the restore-and-update cannot pick a target. Resolve the duplicate rows manually before retrying. What it means
When import_from_dict raises MultipleResultsFound for the dataset itself (legacy exports imported without schemas can collide with later schema'd rows) and the current import was a soft-deleted restore, the code rolls back the deleted_at clear (restoring the original trash timestamp) and raises ImportFailedError: the restore-and-update cannot pick which duplicate row to target, so the operator must deduplicate first. This differs from the live-overwrite path, which keeps the legacy contract of returning the existing row.
Source
Thrown at superset/commands/dataset/importers/v1/utils.py:485
# fail because the UUID match will try to update `examples.NULL.users` to
# `examples.public.users`, resulting in a conflict.
#
# In the soft-deleted-restore case we cannot silently return
# the unmodified row: ``existing.deleted_at`` was already
# cleared above and the operator expects a restore-with-update.
# Returning the row without applying the upload would produce a
# half-restored state. Roll back the ``deleted_at`` clear and
# raise so the operator can resolve the legacy-NULL-schema
# ambiguity before re-uploading.
if is_soft_deleted_match:
# ``is_soft_deleted_match`` is only ever set inside the
# ``if existing := ...`` walrus block, so ``existing`` is
# guaranteed non-None here. The assert pins the invariant
# for mypy.
assert existing is not None
existing.deleted_at = original_deleted_at
db.session.flush()
raise ImportFailedError(
f"Dataset {existing.table_name!r} (uuid {config['uuid']}) "
"matches more than one existing row, so the restore-and-"
"update cannot pick a target. Resolve the duplicate rows "
"manually before retrying."
) from ex
# On the non-soft-deleted overwrite path the legacy contract
# holds: return the existing row unmodified. Bypasses the
# visibility filter so a soft-deleted duplicate can be located
# too — without the bypass the listener would hide the row and
# the ``.one()`` would raise NoResultFound, masking the
# original MultipleResultsFound.
dataset = (
db.session.query(SqlaTable)
.execution_options(**{SKIP_VISIBILITY_FILTER_CLASSES: {SqlaTable}})
.filter_by(uuid=config["uuid"])
.one()
)
View on GitHub (pinned to f4587218dd)
Solutions
- Deduplicate the matching SqlaTable rows in the metadata DB (keep one, purge the others — take a backup first), then retry the import
- If the duplicates are legacy example datasets, removing and re-loading the affected examples can normalize rows
- Contact an admin to reconcile rows via SQL on the metadata database
Defensive patterns
Strategy: try-catch
Validate before calling
# pre-flight: count rows matching the import identity
from superset.models.sql_lab import SqlaTable # adjust import as needed
rows = (
session.query(SqlaTable)
.filter(SqlaTable.uuid == config['uuid'])
.all()
)
if len(rows) > 1:
raise ValueError(f'{len(rows)} rows share uuid {config["uuid"]} — dedupe the metadata DB first') Try / catch
from superset.commands.exceptions import ImportFailedError
try:
import_dataset(config, overwrite=True)
except ImportFailedError as ex:
if 'matches more than one existing row' in str(ex):
# stop: needs operator/DBA dedup; the restore was rolled back automatically
... Prevention
- Monitor the metadata DB for duplicate SqlaTable rows after major upgrades
- Never insert dataset rows by hand without dedupe checks
- Re-load legacy examples with current versions to normalize schema'd rows
When it happens
Trigger: Re-importing an old bundle to restore a soft-deleted dataset while the metadata DB holds more than one row matching the import identity (e.g. legacy NULL-schema rows plus newer schema'd rows sharing uuid/table identity).
Common situations: Instances upgraded from old Superset versions whose example datasets were first imported without schemas and later re-imported with schemas, leaving duplicates; manual DB surgery creating twin rows.
Related errors
- {file_name} has no valid keys
- {file_name} is not a valid file
- ; ".join(str(message) for message in ex.messages)
- Unknown type: {native_type}
- Data URI is not allowed.
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/ca365003a0c2f26f.
Report an issue: GitHub.