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

  1. 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
  2. Permanently delete duplicate/obsolete rows so names are free
  3. Use --verbose to see all conflicting rows instead of the first 5
  4. 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

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


AI-assisted analysis of mlflow/mlflow@6a27f2decc (2026-08-29). Data as JSON: /api/errors/36ec5fe66b50610e. Report an issue: GitHub.