mlflow/mlflow · error · MlflowException

Target database is not empty: table '{table}' has {count} ro

Error message

Target database is not empty: table '{table}' has {count} rows. Migration requires an empty database.

What it means

fs2db requires the target SQL database to be completely empty so migrated records don't collide with existing rows. Before migrating, _assert_empty_db counts rows in the experiments, runs, and registered_models tables; any table with rows aborts the migration with MlflowException. Tables that don't exist are skipped silently.

Source

Thrown at mlflow/store/fs2db/__init__.py:38

        d.name.isdigit() or d.name in {".trash", "models"} for d in source.iterdir() if d.is_dir()
    )
    if has_experiment_dirs:
        return source

    raise MlflowException(f"Cannot find mlruns directory in '{source}'")


def _assert_empty_db(engine) -> None:
    from sqlalchemy import text

    with engine.connect() as conn:
        for table in ("experiments", "runs", "registered_models"):
            try:
                count = conn.execute(text(f"SELECT COUNT(*) FROM {table}")).scalar()
            except Exception:
                continue
            if count > 0:
                raise MlflowException(
                    f"Target database is not empty: table '{table}' has {count} rows. "
                    "Migration requires an empty database."
                )


_ROW_COUNT_QUERIES: dict[str, str] = {
    "experiments": "SELECT COUNT(*) FROM experiments",
    "experiment_tags": "SELECT COUNT(*) FROM experiment_tags",
    "runs": "SELECT COUNT(*) FROM runs",
    "params": "SELECT COUNT(*) FROM params",
    "tags": "SELECT COUNT(*) FROM tags",
    "metrics": "SELECT COUNT(*) FROM metrics",
    "latest_metrics": "SELECT COUNT(*) FROM latest_metrics",
    "datasets": "SELECT COUNT(*) FROM datasets",
    "inputs": "SELECT COUNT(*) FROM inputs WHERE source_type = 'DATASET'",
    "input_tags": "SELECT COUNT(*) FROM input_tags",
    "outputs": "SELECT COUNT(*) FROM inputs WHERE source_type = 'RUN_OUTPUT'",
    "traces": "SELECT COUNT(*) FROM trace_info",

View on GitHub (pinned to 6a27f2decc)

Solutions

  1. Point the migration at a fresh, empty database (or delete the old db file).
  2. If re-running after a failure, drop and recreate the schema before migrating.
  3. Back up the existing database first, then clear it if the old data is no longer needed.

Example fix

# before
migrate(engine, "mlruns")  # mlflow.db has old data
# after
rm mlflow.db && mlflow db upgrade sqlite:///mlflow.db  # fresh empty schema
migrate(engine, "mlruns")
Defensive patterns

Strategy: validation

Validate before calling

from sqlalchemy import create_engine, text
with create_engine(db_uri).connect() as c:
    for t in ("experiments", "runs", "registered_models"):
        try:
            n = c.execute(text(f"SELECT COUNT(*) FROM {t}")).scalar()
        except Exception:
            continue
        if n:
            raise SystemExit(f"DB not empty: {t} has {n} rows; use a fresh database")

Try / catch

try:
    migrate(engine, source)
except MlflowException as e:
    if "Target database is not empty" in str(e):
        raise SystemExit("Point migration at an empty database or clear the existing one")
    raise

Prevention

When it happens

Trigger: Running migrate() against a SQL database that already contains tracking or registry data — e.g. a DB previously used by an MLflow server, or a partially completed earlier migration.

Common situations: Reusing an existing mlflow.db file; re-running a failed migration after some rows were committed; pointing at a shared staging database.

Related errors


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