Skip to content

fix(launcher): install via explicit --python, skipping uv's managed-Python junction (Windows/OneDrive 448)#326

Merged
lstein merged 1 commit into
masterfrom
lstein/fix/launcher-explicit-python
Jun 9, 2026
Merged

fix(launcher): install via explicit --python, skipping uv's managed-Python junction (Windows/OneDrive 448)#326
lstein merged 1 commit into
masterfrom
lstein/fix/launcher-explicit-python

Conversation

@lstein

@lstein lstein commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Problem

On Windows with OneDrive Files-On-Demand, the launcher's first-run install aborts with:

error: Failed to create Python minor version link directory
  Caused by: ... untrusted mount point. (os error 448)

After extensive isolation on the affected machine, this is deterministic on a clean machine (not the transient race #325 assumed): OneDrive's cloud-filter driver cldflt blocks uv's creation of the managed-Python minor-version directory junction on a freshly-created folder tree. The retry from #325 can't help — every attempt hits the same blocked junction — and uv has no flag to skip it (ensure_minor_version_link is unconditional/fatal in uv's source).

Fix

Stop letting uv do a managed-Python install for the tool venv. We still run uv python install to download + extract the interpreter, but treat a nonzero exit as success as long as a usable interpreter landed on disk — the junction is the only thing that fails, and we don't need it. We then point uv tool install at that interpreter via an explicit --python <path>, with UV_PYTHON_INSTALL_DIR unset, so uv treats it as an external interpreter and never attempts the junction. No junction is created → the 448 cannot occur, regardless of timing or OneDrive state.

This is exactly the sequence I verified by hand on the affected machine (uv tool install photomapai --python <extracted python.exe> --torch-backend auto, no UV_PYTHON_INSTALL_DIR) — it installed the full GPU build cleanly.

Details

Tests

go build, go vet, go test, gofmt -l all clean.

Validation plan

Deploy this branch's launcher and run it on a virgin Windows + OneDrive machine (the exact first-run condition that triggered the 448). Expected: installs cleanly with no 448, no retry pauses.

🤖 Generated with Claude Code

…ython junction

The Windows/OneDrive first-run failure (os error 448, "untrusted mount point")
comes from uv creating the managed-Python *minor-version directory junction*.
OneDrive's cloud-filter driver (cldflt) blocks that junction creation on a
freshly-created folder tree; it is deterministic on a clean machine, so the
retry added in #325 cannot help (every attempt hits the same blocked junction).
uv has no flag to skip the junction.

Fix: don't let uv do a managed-Python *install* for the tool venv at all. We
still run `uv python install` to download+extract the interpreter, but we treat
a nonzero exit as success as long as the interpreter landed on disk (the junction
is the only thing that fails, and we don't need it). We then point `uv tool
install` at that interpreter via an explicit `--python <path>` — with
UV_PYTHON_INSTALL_DIR unset, so uv treats it as an external interpreter and never
attempts the junction. No junction is created, so the 448 cannot occur,
regardless of timing or OneDrive state. Verified by hand on the affected machine.

- uvEnv() no longer sets UV_PYTHON_INSTALL_DIR; ensurePython sets it only for the
  download step. uv's python-install output is captured and surfaced only if no
  usable interpreter is found, so the harmless 448 isn't shown.
- Removes the now-ineffective retry machinery (withRetry/runUVRetry) from #325.
- Keeps --no-bin (no python shim in ~/.local/bin) and #324's macOS Xcode warning.
- Adds a unit test for findExtractedPython; updates the uvEnv test for the new
  contract.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
lstein added a commit that referenced this pull request Jun 9, 2026
…rive, macOS)

Add a 1.1.0 release-note bullet for the launcher install-reliability work landed
after the notes were first drafted: the Windows/OneDrive 'untrusted mount point'
first-run fix (#326) and the macOS Xcode Command Line Tools prompt guidance
(#324).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lstein lstein merged commit 7f10570 into master Jun 9, 2026
13 checks passed
lstein added a commit that referenced this pull request Jun 9, 2026
)

* chore(release): bump version to 1.1.0

Go directly to 1.1.0 (skipping 1.0.6 and 1.1.0rc1). Since 1.0.5 there have been
22 features and no breaking changes, including the signed uv-bootstrap desktop
launcher (#300), UMAP cluster auto-labeling (#234), per-device UI preferences
(#284), Move-to-Trash deletion (#273), and Python 3.14 support (#258) — a minor
bump, not a patch. Version is single-sourced here (get_version() in args.py
reads importlib.metadata).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(release): add 1.1.0 release notes

Add docs/release-notes.md (changelog-style, newest version first) summarizing
the 1.1.0 changes since 1.0.5, grouped by theme. Wire it into the mkdocs nav.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(release): note first-run install reliability fixes (Windows/OneDrive, macOS)

Add a 1.1.0 release-note bullet for the launcher install-reliability work landed
after the notes were first drafted: the Windows/OneDrive 'untrusted mount point'
first-run fix (#326) and the macOS Xcode Command Line Tools prompt guidance
(#324).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: remove extraneous claude brags

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant