astral-sh/ruff · error

Lockfile not found at '{lockfile_path}'. Run with `MDTEST_UP

Error message

Lockfile not found at '{lockfile_path}'. Run with `MDTEST_UPGRADE_LOCKFILES=1` to generate it.

What it means

When setup_venv runs in normal (locked) mode it copies the committed uv.lock into the temporary venv directory before `uv sync`. If the expected lockfile does not exist on disk, the harness bails and tells you to regenerate it with MDTEST_UPGRADE_LOCKFILES=1.

Source

Thrown at crates/ty_test/src/external_dependencies.rs:88

        },
        PythonPlatform::All => {
            bail!("For an mdtest with external dependencies, a Python platform must be specified");
        }
    };

    let upgrade_lockfile = std::env::var("MDTEST_UPGRADE_LOCKFILES").is_ok_and(|v| v == "1");
    let use_locked = if upgrade_lockfile {
        // In upgrade mode, we'll generate a new lockfile
        false
    } else if lockfile_path.exists() {
        // Copy existing lockfile to temp directory
        let temp_lockfile = temp_path.join("uv.lock");
        std::fs::copy(lockfile_path, temp_lockfile.as_std_path())
            .with_context(|| format!("Failed to copy lockfile from '{lockfile_path}'"))?;
        true
    } else {
        // No existing lockfile - error in normal mode
        bail!(
            "Lockfile not found at '{lockfile_path}'. Run with `MDTEST_UPGRADE_LOCKFILES=1` to generate it.",
        );
    };

    // Run `uv sync` to install dependencies
    let mut uv_sync = std::process::Command::new("uv");
    uv_sync
        .args(["sync", "--python-platform", uv_platform])
        .current_dir(temp_path.as_std_path());
    if use_locked {
        uv_sync.arg("--locked");
    }

    let uv_sync_output = uv_sync
        .output()
        .context("Failed to run `uv sync`. Is `uv` installed?")?;

    if !uv_sync_output.status.success() {

View on GitHub (pinned to 26f38c119c)

Solutions

  1. Run once with MDTEST_UPGRADE_LOCKFILES=1 (plus MDTEST_EXTERNAL=1) to generate the lockfile, then commit it
  2. Or run `uv run crates/ty_python_semantic/mdtest.py -e external/` which manages this for you
  3. Verify uv.lock exists at the path referenced by the mdtest's external-dependencies config

Example fix

// before
MDTEST_EXTERNAL=1 cargo test -p ty_python_semantic --test mdtest mdtest__external
// after
MDTEST_EXTERNAL=1 MDTEST_UPGRADE_LOCKFILES=1 cargo test -p ty_python_semantic --test mdtest mdtest__external
# then commit the generated uv.lock and re-run in locked mode
Defensive patterns

Strategy: validation

Validate before calling

lockfile="crates/ty_python_semantic/resources/mdtest/external/uv.lock"
[ -f "$lockfile" ] || { echo "missing $lockfile; run with MDTEST_UPGRADE_LOCKFILES=1"; exit 1; }

Try / catch

match std::path::Path::new(lockfile_path).try_exists() {
    Ok(true) => proceed(),
    Ok(false) => eprintln!("Lockfile missing at {lockfile_path}; set MDTEST_UPGRADE_LOCKFILES=1"),
    Err(e) => eprintln!("cannot stat lockfile: {e}"),
}

Prevention

When it happens

Trigger: Running an external-dependency mdtest (MDTEST_EXTERNAL=1) where the uv.lock next to the mdtest directory was never committed, was deleted, or the test was moved/renamed so its lockfile path no longer matches.

Common situations: Adding a new external mdtest without generating its lockfile; a fresh clone missing generated artifacts; renaming the external/ subdirectory without moving uv.lock.

Related errors


AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05). Data as JSON: /api/errors/fb0e5a01df3d70e1. Report an issue: GitHub.