Fix: uv Not Working — Command Not Found, Python Version Error, and Lock File Conflicts
Quick Answer
How to fix uv errors — uv command not found after install, no Python interpreter found, uv run vs activate confusion, uv.lock merge conflicts, uv pip vs uv add, migrating from pip and Poetry, and workspace resolution failures.
The Error
You install uv and the command isn’t found:
uv: command not foundOr uv can’t find the Python version your project needs:
error: No interpreter found for Python 3.11 in virtual environments,
managed installations, or search pathOr you run uv sync and the packages vanish when you open a new terminal:
uv sync
python -c "import requests" # Works
# Open new terminal
python -c "import requests" # ModuleNotFoundErrorOr merging two feature branches breaks the lock file:
error: Failed to parse `uv.lock`: TOML parse error at line 47uv is fast and opinionated — it manages Python versions, virtual environments, and dependencies together. Most issues come from expecting pip or Poetry behavior from a tool that works differently by design.
Why This Happens
uv separates concerns sharply: uv add manages project dependencies (modifying pyproject.toml and uv.lock), uv pip manages environments directly (like pip), and uv run handles execution with automatic environment sync. Using the wrong command for the wrong context is the source of most confusion.
Python version management is also built in — uv downloads and manages its own Python installations independently of whatever Python is on your system. This is intentional and usually works seamlessly, but requires understanding when it applies.
Fix 1: uv: command not found — Installation and PATH
After running the install script, uv goes to ~/.local/bin/ but that directory may not be in your shell’s PATH.
Install uv:
# macOS / Linux (standalone installer — recommended)
curl -LsSf https://astral.sh/uv/install.sh | sh
# macOS (Homebrew)
brew install uv
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# Windows (winget)
winget install --id=astral-sh.uv -eIf uv still isn’t found after installing, the issue is PATH. The installer adds a line to your shell config, but that line only takes effect in new terminal sessions.
Either open a new terminal, or source your config manually:
# Bash
source ~/.bashrc
# Zsh
source ~/.zshrcIf you’re in a shell that doesn’t source either of those (e.g., a non-login shell in some CI environments), add the path explicitly:
export PATH="$HOME/.local/bin:$PATH"To make it permanent, add that line to your ~/.bashrc or ~/.zshrc.
Windows: uv installs to %USERPROFILE%\.local\bin. Add this to your system PATH via System Properties → Advanced → Environment Variables, or in PowerShell:
$env:PATH = "$env:USERPROFILE\.local\bin;$env:PATH"Verify the install worked:
uv --version
# uv 0.6.x (yyyy-mm-dd)Fix 2: Python Version Not Found
error: No interpreter found for Python 3.12 in virtual environments,
managed installations, or search pathuv manages its own Python installations separately from any Python you’ve installed through Homebrew, pyenv, or the system package manager. If a project requires Python 3.12 and uv hasn’t downloaded it yet, you get this error.
Install the required Python version through uv:
uv python install 3.12
# Install multiple versions at once
uv python install 3.11 3.12 3.13
# List all available versions
uv python list
# List only installed versions
uv python list --only-installedPin the Python version for your project by creating a .python-version file:
uv python pin 3.12
# Creates .python-version containing "3.12"This tells uv which version to use for this project. Commit the .python-version file so everyone on the team uses the same version.
If you want to use the system Python rather than uv’s managed version:
uv run --python $(which python3) script.py
# Or set it in pyproject.toml to point to a system Python
uv python pin /usr/bin/python3.12Common cause of version conflicts: requires-python in pyproject.toml and .python-version disagreeing:
# pyproject.toml says 3.10+
[project]
requires-python = ">=3.10"# .python-version says 3.9
3.9.18uv enforces requires-python strictly. Fix by updating .python-version:
uv python pin 3.11 # Within the >=3.10 rangePro Tip: uv automatically downloads missing Python versions by default. If you’re on a restricted network or an air-gapped machine, disable this with UV_PYTHON_DOWNLOADS=never to force uv to only use already-installed interpreters.
Fix 3: Packages Missing in New Terminal — uv run vs Manual Activation
This is the single most common source of confusion for developers coming from pip. uv sync creates a virtual environment in .venv/, but that environment is only active in the current shell session if you explicitly activate it.
uv sync # Creates .venv, installs packages
python -c "import requests" # Works — because .venv/bin is first in PATH?
# No — this depends on whether you activated itThe uv way: use uv run instead of activating:
uv run python script.py
uv run pytest
uv run flask runuv run automatically syncs the environment to the current lockfile and then executes the command. You never need to activate anything — uv handles it per-invocation.
When you do need manual activation (for interactive sessions or IDE setup):
# Create and sync the environment first
uv sync
# Activate
source .venv/bin/activate # Linux/macOS bash/zsh
.venv\Scripts\Activate.ps1 # Windows PowerShell
.venv\Scripts\activate.bat # Windows cmd
# Now python/pip refer to the venv
python script.py
# Deactivate when done
deactivateFor IDEs (VS Code, PyCharm): point the interpreter to .venv/bin/python (Linux/macOS) or .venv\Scripts\python.exe (Windows). The IDE will activate the environment automatically for its terminal.
Why packages disappear in a new terminal: the environment exists in .venv/ and is always there — it just isn’t active unless you activate it or use uv run. The packages didn’t go anywhere; your shell just doesn’t know to look in .venv/bin first.
Fix 4: uv.lock Conflicts After Merging Branches
uv.lock is a machine-generated file that fully specifies the dependency resolution for every supported platform. When two branches both modify dependencies independently, merging them produces a broken lock file with TOML syntax errors — it can’t be resolved manually like a regular merge conflict.
The fix: always regenerate the lock file after a merge conflict on it:
# After seeing merge conflict markers in uv.lock:
rm uv.lock # Delete the broken file
uv lock # Regenerate from scratch based on pyproject.tomlIf both branches added different packages, pyproject.toml will also have merge conflicts. Resolve those first (they’re readable), then regenerate the lock:
# 1. Fix pyproject.toml conflicts manually
# 2. Then regenerate
uv lockCommit the regenerated uv.lock — it should be tracked in git. Every team member running uv sync will then get a deterministic, identical environment.
For dependency version conflicts (where two packages need incompatible versions of a third package):
error: Because package-a==1.0 requires dep>=2.0 and package-b==3.0 requires dep<2.0,
we can't satisfy all constraints.View what’s constraining the resolution:
uv lock --verboseTry upgrading to newer versions that may have resolved the constraint:
uv lock --upgrade # Upgrade everything within allowed ranges
uv lock --upgrade-package package-a # Upgrade one package specificallyIf the conflict is genuine (two packages truly can’t coexist), you need to replace one of them or find a version combination that works. Run uv lock --verbose and read the resolution output to understand which package is pulling in the conflicting requirement.
Fix 5: uv pip install vs uv add — Which One to Use
uv has two distinct package management modes. Using the wrong one leads to packages that seem installed but aren’t tracked, or packages that don’t appear in the environment you expect.
uv add — use this for project development:
uv add requests # Adds to [project.dependencies] in pyproject.toml
uv add --dev pytest # Adds to dev dependencies
uv add "django>=4.2" # With version constraint
uv remove requests # Removes from pyproject.toml and uv.lockuv add modifies pyproject.toml, updates uv.lock, and installs into the project’s .venv. This is the equivalent of poetry add — dependencies are tracked and reproducible.
uv pip install — use this for one-off installs or when working without a project:
uv pip install requests # Installs to the active virtual environment
uv pip install -r requirements.txt # Install from requirements file
uv pip sync requirements.txt # Sync env to EXACTLY match requirements.txt (removes extras)uv pip install doesn’t touch pyproject.toml. It installs directly to whatever environment is active (or to a default location if none is active). Use it for quick experimentation or for pip-style workflows without a full project structure.
Common Mistake: Running uv pip install requests in a project directory and wondering why uv sync later removes it. uv sync brings the environment in line with uv.lock, which was generated from pyproject.toml. Since requests wasn’t in pyproject.toml, uv sync removes it. Use uv add requests instead.
The mental model: uv add = “this is part of my project”, uv pip install = “put this in the environment right now”.
Fix 6: Migrating from pip / Poetry / pyenv
From pip + requirements.txt:
# Initialize a new uv project in an existing directory
uv init
# Import dependencies from requirements.txt
uv add -r requirements.txt
# Import dev dependencies
uv add --dev -r requirements-dev.txt
# Generate the lock file
uv lockThe uv.lock file replaces pip freeze > requirements.txt for reproducible installs. Other developers run uv sync instead of pip install -r requirements.txt.
From Poetry:
uv uses the same pyproject.toml format as Poetry, but the section headers differ:
# Poetry (old)
[tool.poetry.dependencies]
python = "^3.11"
requests = "^2.31"
[tool.poetry.dev-dependencies]
pytest = "^7.0"
# uv (new)
[project]
requires-python = ">=3.11"
dependencies = ["requests>=2.31"]
[project.optional-dependencies]
dev = ["pytest>=7.0"]Migration steps:
# Remove Poetry files
rm poetry.lock
# Initialize uv (keeps pyproject.toml, just changes the format)
uv init --no-readme
# Add dependencies from the old [tool.poetry.dependencies] section
uv add requests # Repeat for each dependency
# Add dev dependencies
uv add --dev pytest
# Sync and verify
uv sync
uv run pytestFrom pyenv:
pyenv manages Python versions at the system level; uv manages them at the project level. They can coexist, but once you use uv python install, you usually don’t need pyenv for Python version management anymore:
# Check what pyenv has
pyenv versions
# Install the same version in uv
uv python install 3.11.7
# Pin for the project
uv python pin 3.11.7
# uv now uses its own 3.11.7, not pyenv'sIf you want uv to use pyenv’s Python (to share a single installation), point uv python pin at the pyenv binary:
uv python pin $(pyenv which python3.11)For package installation errors that arise during migration — like packages that fail to build from source — see Python packaging not working and pip could not build wheels.
Fix 7: Inline Script Dependencies — PEP 723 Syntax
uv supports PEP 723 inline script metadata, which lets you declare dependencies directly in a single .py file. The syntax is strict — any deviation causes a silent parse failure.
Correct format:
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "requests>=2.31",
# "click>=8.0",
# ]
# ///
import requests
import click
@click.command()
@click.argument("url")
def fetch(url):
print(requests.get(url).text[:200])
if __name__ == "__main__":
fetch()Run it:
uv run fetch.py https://example.com
# uv automatically creates an isolated env, installs deps, runs the scriptCommon syntax errors that silently break parsing:
# WRONG — trailing space after ///
# /// ← space here breaks it
# WRONG — empty line without # prefix
# /// script
# dependencies = ["requests"]
# ← this empty line breaks it
# ///
# CORRECT — every line in the block starts with #
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "requests>=2.31",
# ]
# ///If uv ignores your inline dependencies and says the package isn’t found, it’s almost always a whitespace issue in the block.
Add dependencies to an existing script via CLI (instead of editing manually):
uv add --script fetch.py requests clickThis correctly inserts the block with proper formatting.
Lock a script’s dependencies for reproducibility:
uv lock --script fetch.py
# Creates fetch.py.lock alongside the scriptFix 8: Workspace Resolution Failures
Workspaces let you manage multiple related Python packages in one repository with a shared uv.lock. When they break, the error is usually a dependency version conflict between members or a missing pyproject.toml in a member directory.
Workspace setup (root pyproject.toml):
[tool.uv.workspace]
members = [
"packages/api",
"packages/worker",
"packages/shared",
]Each member directory needs its own pyproject.toml:
# packages/api/pyproject.toml
[project]
name = "api"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
"fastapi>=0.110",
"shared", # Another workspace member
]
[tool.uv.sources]
shared = { workspace = true } # Tells uv this is a workspace member, not PyPIError: workspace member not found:
error: Workspace member `packages/api` not foundCheck that:
- The directory exists and contains a
pyproject.toml - The glob pattern in
membersmatches the actual path - No typos in the path string
ls packages/api/pyproject.toml # Must existError: conflicting dependency versions between members:
error: Because api requires requests==2.28.0 and worker requires requests>=2.31.0,
we can't satisfy all requirements.All workspace members share a single lock file, so their dependencies must be jointly resolvable. Fix by aligning version constraints:
# Change from exact pins to ranges in all affected members
dependencies = ["requests>=2.28.0,<3"] # Both members can agree on thisRun a command in a specific workspace member:
uv run --package api python -m uvicorn app:main
uv run --package worker python -m celery workerStill Not Working?
uv sync Is Slow or Re-downloads Everything
uv caches downloaded packages in ~/.cache/uv/ (Linux/macOS) or %LOCALAPPDATA%\uv\cache (Windows). If the cache is missing or corrupted:
uv cache clean # Clear the cache
uv sync # Re-download (will be fast after the first time)On CI/CD, cache the uv cache directory between runs to avoid re-downloading packages on every build:
# GitHub Actions example
- uses: actions/cache@v4
with:
path: ~/.cache/uv
key: uv-${{ hashFiles('uv.lock') }}Package Installs But import Fails
If uv add requests reports success but uv run python -c "import requests" fails, check which environment is active:
uv run python -c "import sys; print(sys.executable)"
# Should print: /path/to/your/project/.venv/bin/python
# If it prints a system Python path, uv is using the wrong interpreter
# Run from within the project directory, not a parentuv uses the pyproject.toml in the current directory to locate the project. If you run uv run from a parent directory, it may not find the project and use a fallback environment.
Editable Installs and Package Not Found in Workspace
If a workspace member’s package code isn’t importable despite being in the workspace:
uv sync --editable # Install workspace members as editableOr add editable = true in the workspace source:
[tool.uv.sources]
shared = { workspace = true, editable = true }Comparing uv with pip and Poetry
uv doesn’t replace pip entirely — uv pip is pip-compatible for environments and scripts. The project management commands (uv init, uv add, uv sync) replace Poetry and pip-tools. For understanding how requires-python and virtual environment isolation work at a deeper level, see Python virtualenv wrong Python and Python ModuleNotFoundError venv.
Build Failures for Packages with C Extensions
Some packages (numpy, cryptography, psycopg2) compile C code during installation. If compilation fails:
# Show the full build log
uv add --verbose cryptography
# Use a pre-built wheel instead of building from source
uv add --no-build-isolation cryptography
# On macOS: ensure Xcode tools are installed
xcode-select --installBuild failures during uv add are usually a missing system library or compiler, not a uv issue. The error output from the failed build contains the actual cause. See Python packaging not working for the full set of build error patterns.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Poetry Dependency Conflict (SolverProblemError / No Solution Found)
How to fix Poetry dependency resolution errors — SolverProblemError when adding packages, conflicting version constraints, how to diagnose dependency trees, and workarounds for incompatible packages.
Fix: Python venv Using Wrong Python Version
How to fix Python virtual environments using the wrong Python version — venv picking system Python instead of pyenv, specifying the interpreter path, and verifying the active environment.
Fix: Apache Airflow Not Working — DAG Not Found, Task Failures, and Scheduler Issues
How to fix Apache Airflow errors — DAG not appearing in UI, ImportError preventing DAG load, task stuck in running or queued, scheduler not scheduling, XCom too large, connection not found, and database migration errors.
Fix: Dash Not Working — Callback Errors, Pattern Matching, and State Management
How to fix Dash errors — circular dependency in callbacks, pattern matching callback not firing, missing attribute clientside_callback, DataTable filtering not working, clientside JavaScript errors, Input Output State confusion, and async callback delays.