Skip to content

uv pip install --python <venv> fails for a cpython-*-emscripten-wasm32-musl venv on Windows — malformed path mixing POSIX and Windows conventions #21199

Open

Description

@mittalpk

Summary

uv venv --python cpython-3.13.2-emscripten-wasm32-musl creates a venv with a Windows-native layout (Lib\site-packages, Scripts\), but a subsequent uv pip install --python <that-venv> crashes trying to create a malformed, POSIX-style path (//lib/python3.13/site-packages\) that doesn't match the venv it just created.

Reproduction

uv venv myvenv --python cpython-3.13.2-emscripten-wasm32-musl
Get-Content myvenv\pyvenv.cfg
# home = C:\Users\...\AppData\Roaming\uv\python\pyodide-3.13.2-emscripten-wasm32-musl
# implementation = CPython
# version_info = 3.13.2

Get-ChildItem -Recurse myvenv | Select-Object FullName
# myvenv\Lib\site-packages exists (Windows-native layout)
# myvenv\Scripts\python.exe exists

uv pip install --python myvenv --no-build click

Expected

Installs into myvenv\Lib\site-packages (matching the layout uv venv itself just created), or errors clearly if that's unsupported.

Actual

Using Python 3.13.2 environment at: /
Resolved 1 package in 514ms
Prepared 1 package in 63ms
error: Failed to install: click-8.4.2-py3-none-any.whl (click==8.4.2)
  Caused by: Failed to create directory `//lib/python3.13/site-packages\`
  Caused by: failed to create directory `//lib/python3.13/site-packages\`: The network path was not found. (os error 53)

Two things stand out:

  1. The resolved "environment at" is /, not the real venv path — same result whether --python points at the venv directory or directly at myvenv\Scripts\python.exe.
  2. The target path mixes forward slashes (matching the emscripten target's own embedded POSIX scheme) with a trailing backslash, and isn't rooted anywhere valid on Windows (// reads as a UNC prefix, hence "network path not found").

This looks like a disagreement between two parts of uv: uv venv correctly uses the host's layout convention for the venv skeleton, but uv pip install --python for that same venv instead consults the target interpreter's own embedded (POSIX) scheme — and the two don't agree.

Related

Possibly adjacent to #19963 (closed as "working as intended" for --prefix + --python-platform), but this is a different code path — a real venv with its own pyvenv.cfg already exists here, created by uv venv itself for this exact interpreter, and uv pip install --python still doesn't agree with it.

Version

uv 0.12.5 (210d1f6 2026-08-14 x86_64-pc-windows-msvc), Windows

Context

Found while investigating cloudflare/workers-py#211, where this causes Python Workers deploys to fail (reported as cloudflare/workers-sdk#15208).

Activity

  1. mittalpk commented on Aug 18, 2026

    @mittalpk
    Author

    Dug a bit further into the source to narrow down where this might live, in case it's useful.

    uv venv itself computes the venv's scheme correctly — crates/uv-virtualenv/src/virtualenv.rs:625 builds VirtualEnvironment { scheme: Scheme { purelib: location.join(&interpreter.virtualenv().purelib), ... } }, which is why the venv this creates genuinely has Lib\site-packages on Windows (confirmed via Get-ChildItem/pyvenv.cfg above). But that computed Scheme only exists in memory for that one uv venv invocation — it's never persisted to disk (pyvenv.cfg doesn't record it).

    A later, separate uv pip install --python <that venv> process has to independently re-derive the same layout, presumably by reading pyvenv.cfg's home = ... line and re-introspecting the interpreter it points at (InterpreterInfo::query/with_virtualenv in crates/uv-python/src/interpreter.rs).

    Working hypothesis: the two code paths disagree on what determines the layout. uv venv's own creation logic appears to use the host OS (correctly landing on Lib\site-packages for a Windows host). The re-derivation path used by later commands may instead be keying off the interpreter's own self-reported os_name marker — which for a Pyodide/emscripten CPython build is almost certainly posix, regardless of the host it's actually running on. That would explain the exact malformed path observed (//lib/python3.13/site-packages\) and would be invisible for every normal interpreter, since a native interpreter's self-reported OS always matches its real host by definition — this foreign-target case is the one place that assumption breaks.

    I haven't pinned the exact line where the interpreter's os_name marker feeds into the second code path's layout decision, and don't have a Rust build set up to verify by patching and testing directly, but wanted to share the narrowed-down lead in case it's a useful starting point.

  2. joshuavetos commented on Aug 30, 2026

    @joshuavetos

    Hey, I’d be interested in taking a look at this. The Windows/Pyodide venv path mismatch seems pretty well isolated, especially around the difference between venv creation and later --python re-discovery. Would you be open to a PR if I can reproduce it on current main and add a regression test?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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