mlflow/mlflow · error · RuntimeError
Move aborted: merging workspaces would create duplicate {res
Error message
Move aborted: merging workspaces would create duplicate {resource_description}. Resolve the following conflicts by renaming the affected resources (restore deleted ones first) or permanently deleting them, then retry: {formatted_conflicts} What it means
During migration of a legacy (no-workspace) database into the default workspace, _assert_no_workspace_conflicts checks whether moving rows into the target workspace would violate uniqueness (same name/experiment_id etc. already existing in the default workspace, including soft-deleted rows). If duplicates would result, it aborts with a RuntimeError listing the conflicting rows so nothing is silently merged.
Source
Thrown at mlflow/store/db/workspace_migration.py:89
sa.select(*group_columns).group_by(*group_columns).having(sa.func.count() > 1).subquery()
)
join_conditions = [table.c[column] == conflict_keys.c[column] for column in columns]
extra_columns = []
if table_name == "experiments" and "experiment_id" in table.c:
extra_columns.append(table.c.experiment_id)
conflict_rows_stmt = (
sa
.select(*group_columns, table.c.workspace, *extra_columns)
.select_from(table.join(conflict_keys, sa.and_(*join_conditions)))
.order_by(*group_columns, table.c.workspace, *extra_columns)
)
if conflicts := conn.execute(conflict_rows_stmt).fetchall():
formatted_conflicts = _format_conflicts(
conflicts,
(*columns, "workspace", *(column.name for column in extra_columns)),
max_rows=None if verbose else 5,
)
raise RuntimeError(
"Move aborted: merging workspaces would create duplicate "
f"{resource_description}. Resolve the following conflicts by renaming the affected "
"resources (restore deleted ones first) or permanently deleting them, then retry: "
f"{formatted_conflicts}"
)
def migrate_to_default_workspace(
engine: sa.Engine,
dry_run: bool = False,
*,
verbose: bool = False,
) -> dict[str, int]:
"""
Move all workspace-scoped resources into the default workspace.
Returns a mapping of table name -> number of rows moved (or that would be moved in dry-run).
When verbose is True, conflict lists are not truncated.
"""View on GitHub (pinned to 6a27f2decc)
Solutions
- Read formatted_conflicts in the message and rename the offending resources in one side (restore soft-deleted ones first, rename, or delete them permanently), then re-run the migration
- Permanently delete duplicate/obsolete rows so names are free
- Use --verbose to see all conflicting rows instead of the first 5
- Restore deleted resources listed in conflicts, rename or purge them, then retry
Example fix
# before: duplicate experiment 'bert-prod' exists in both places mlflow db migrate-workspaces --backend-store-uri sqlite:///mlflow.db # RuntimeError listing conflicts # after: rename the legacy experiment first mlflow experiments rename --experiment-name bert-prod --new-name bert-prod-legacy mlflow db migrate-workspaces --backend-store-uri sqlite:///mlflow.db
Defensive patterns
Strategy: validation
Validate before calling
# Pre-check for name collisions before migrating
from mlflow.tracking import MlflowClient
c = MlflowClient()
existing = {e.name for e in c.search_experiments(view_type=mlflow.entities.ViewType.ALL)}
legacy_names = {'exp-a', 'exp-b'} # names present in the pre-migration DB
conflicts = existing & legacy_names
if conflicts:
raise SystemExit(f'Rename or delete duplicates first: {conflicts}') Try / catch
import subprocess
r = subprocess.run(['mlflow', 'db', 'migrate-workspaces', ...], capture_output=True, text=True)
if r.returncode != 0 and 'Move aborted: merging workspaces would create duplicate' in r.stderr:
resolve_conflicts_from_report(r.stderr)
subprocess.run([...], check=True) # retry Prevention
- Run migration on a fresh backup/clone so the default workspace is empty
- Restore and permanently purge soft-deleted duplicates before migrating
- Use --verbose to see the full conflict list
- Do a dry run against a staging copy of the DB first
When it happens
Trigger: Running `mlflow db migrate-workspaces` (migrate_to_default_workspace) on a DB where the default workspace already contains resources whose names/keys collide with ones in the legacy root: duplicate experiment names, registered model names, or prompt names, including soft-deleted rows.
Common situations: Re-running migration after a partial move, having created new experiments/models in the default workspace before migrating legacy data, soft-deleted resources still occupying names.
Related errors
- Move aborted: the following {resource_type} already exist in
- Downgrade aborted: merging workspaces would create duplicate
- Aborted: the database does not have workspaces enabled. This
- Aborted: the database does not have workspaces enabled. This
- Aborted: the database does not have workspaces enabled. This
AI-assisted analysis of mlflow/mlflow@6a27f2decc (2026-08-29).
Data as JSON: /api/errors/36ec5fe66b50610e.
Report an issue: GitHub.