Skip to content

uv python install --reinstall cannot recover a dangling minor-version-link junction on Windows: "Missing expected target directory for Python minor version link" #19622

Description

Summary

On Windows, if the managed-Python minor version link junction (e.g. cpython-3.13-windows-x86_64-none) becomes dangling, every subsequent uv python install / uv python install --reinstall / uv run fails with:

error: Missing expected target directory for Python minor version link at C:\Users\<user>\AppData\Roaming\uv\python\cpython-3.13.13-windows-x86_64-none

uv does not self-heal this. --reinstall re-downloads and re-extracts the interpreter, but still fails at the link step, and re-creates a junction that also does not resolve. Even deleting the patch directory and .temp entirely and running a clean uv python install 3.13 reproduces the identical error. The only thing that fixes it is manually deleting the dangling junction and recreating it with a native Windows junction.

Environment

On-disk state when broken

%APPDATA%\Roaming\uv\python\:

  • cpython-3.13.13-windows-x86_64-none — real directory, complete and working. python.exe -V => Python 3.13.13 (exit 0); full stdlib present.
  • cpython-3.13-windows-x86_64-none — a Junction whose Target correctly reads ...\cpython-3.13.13-windows-x86_64-none, but which enumerates 0 children (dangling at the OS level / does not resolve).

So the interpreter is fine; only the minor-version-link junction is broken, and that one broken junction poisons discovery and install.

Reproduction (verbose)

uv python install 3.13 --reinstall -v (stderr):

DEBUG Found download `cpython-3.13.13-windows-x86_64-none` for request `3.13 (cpython-3.13-windows-x86_64-none)`
DEBUG Downloading https://releases.astral.sh/github/python-build-standalone/releases/download/20260510/cpython-3.13.13%2B20260510-x86_64-pc-windows-msvc-install_only_stripped.tar.gz
DEBUG Extracting ... to temporary location: ...\uv\python\.temp\.tmpXXXXXX
Downloading cpython-3.13.13-windows-x86_64-none (download) (20.8MiB)
 Downloaded cpython-3.13.13-windows-x86_64-none (download)
DEBUG Removing existing directory: ...\uv\python\cpython-3.13.13-windows-x86_64-none
DEBUG Moving ...\uv\python\.temp\.tmpXXXXXX\python to ...\uv\python\cpython-3.13.13-windows-x86_64-none
DEBUG Inspecting existing executable at `C:\Users\<user>\.local\bin\python3.13.exe`
error: Missing expected target directory for Python minor version link at ...\uv\python\cpython-3.13.13-windows-x86_64-none

Observations:

  1. The patch directory is re-created by the move and is valid, yet the install still fails at the minor-version-link step (exit code 2).
  2. --reinstall does not remove/replace the pre-existing dangling cpython-3.13-... junction; the run ends with that junction still present and still enumerating 0 children.
  3. Deleting the patch dir and .temp, then uv python install 3.13 from a clean state, fails identically.
  4. When uv itself (re)creates the cpython-3.13-... junction during install, the result does not resolve (0 children). A junction created manually to the same target (New-Item -ItemType Junction / mklink /J) does resolve.

Workaround that actually fixes it

$base = "$env:APPDATA\uv\python"
$link = Join-Path $base 'cpython-3.13-windows-x86_64-none'
$patch = Join-Path $base 'cpython-3.13.13-windows-x86_64-none'
[System.IO.Directory]::Delete($link, $false)   # remove the dangling junction only (leaves the patch dir intact)
New-Item -ItemType Junction -Path $link -Target $patch | Out-Null

After this, uv python list --only-installed shows cpython-3.13.13 and uv run/uv python find use it normally.

Suggested fix

ensure_minor_version_link() should be idempotent / self-healing on Windows: if a minor-version-link junction already exists but does not resolve to a valid target (dangling reparse point), remove and recreate it rather than erroring with "Missing expected target directory". Discovery (find_all) could likewise treat a non-resolving managed-install junction as repairable/ignorable instead of hard-failing the whole operation.

Possibly related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions