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

@NextLevelManagementAdvisors

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions