Released connected 2026-07-28.
Since we released uv 0.11.0 successful March, we've accumulated changes that amended correctness, safety, and compatibility pinch specifications, but could break immoderate workflows. This merchandise contains those changes; galore person been marked arsenic breaking retired of an abundance of caution.
We expect astir users to beryllium capable to upgrade without making changes.
There are nary breaking changes to the configuration of the uv build backend. If your [build-system] array includes an precocious bound connected uv_build, update it to let uv_build 0.12, e.g., uv_build>=0.11.32,<0.13.
Define build systems by default pinch uv init (#19197)
Projects created pinch uv init now state a build strategy and are packaged by default. This was the default task layout each the measurement backmost successful v0.3, but we recovered that the usage of the hatchling build strategy was confusing to newcomers and result dropped usage of a build strategy by default successful v0.4. Since then, we've created our ain build strategy (uv_build) pinch tight integration pinch uv and are excited to reconstruct the default to a best-practice task layout.
Previously, uv init illustration created an unpackaged layout containing main.py and a pyproject.toml without a build system. The task could state limitations but was not itself installed into its virtual environment.
Now, uv init illustration defines a [build-system] utilizing uv_build, places exertion root codification successful src/example, and includes a [project.scripts] introduction named example. Defining a build strategy allows the task to beryllium imported from tests aliases different code, installed arsenic a dependency, and tally arsenic a command:
Existing projects are unaffected. Use uv init --no-package example to create the erstwhile unpackaged layout without a build system.
See the project creation documentation for much details.
This stabilizes the packaged-init preview feature.
Reject unsupported root distribution and instrumentality archive formats (#18927)
PEP 625 requires source distributions to usage .tar.gz archives. Previously, uv besides accepted bequest formats specified arsenic .tar.bz2 and .tar.xz. Those formats are now rejected, including erstwhile referenced by an existing lockfile. Legacy .zip root distributions stay supported for backwards compatibility.
Wheels and different ZIP archives tin nary longer incorporate entries compressed pinch bzip2, LZMA, aliases XZ. Entries must usage the stored, DEFLATE, aliases zstd compression methods.
Removing support for uncommon compression methods reduces uv's compression limitations and the onslaught aboveground exposed erstwhile processing untrusted packages.
You cannot opt retired of this behavior. If you dangle connected a bequest root distribution that uses an unsupported format, we urge rebuilding it arsenic a .tar.gz archive and regenerating immoderate lockfile containing references to the bequest archive.
Reject instrumentality files that could switch the Python interpreter (#20748, #20749)
uv already rejected instrumentality introduction points named python, but lawsuit variants specified arsenic Python were still accepted. On case-insensitive filesystems, including communal macOS and Windows setups, these introduction points could overwrite the virtual environment's interpreter.
Wheels could besides spot expert files successful their .data/scripts directory aliases successful paths specified arsenic .data/data/bin/python, bypassing the entry-point cheque and replacing the expert during installation.
uv now rejects case-insensitive variants of reserved expert names and instrumentality information files that would beryllium installed complete an interpreter. This includes names specified arsenic Python, python.py, and Python.exe, on pinch different reserved expert names and their versioned variants.
You cannot opt retired of these checks. Rename conflicting introduction points aliases instrumentality information files and rebuild the affected wheel.
Prefer unchangeable releases earlier falling backmost to pre-releases (#19993)
A dependency tin present a pre-release requirement aft solution starts. uv antecedently required each package's pre-release eligibility to beryllium known earlier solution began: the default if-necessary-or-explicit mode allowed them for nonstop requirements that explicitly requested a pre-release, aliases for packages that only published pre-releases.
This meant that a pre-release request discovered successful a dependency's metadata, e.g., example>=2.0.0b1, would neglect to resoluteness moreover erstwhile a compatible pre-release existed. To resoluteness it, you had to adhd that dependency arsenic a nonstop request aliases let pre-releases crossed your full dependency graph.
The default mode is now if-necessary. uv tries unchangeable candidates first and falls backmost to pre-releases erstwhile nary unchangeable campaigner satisfies the progressive constraints. Like pip, uv now supports pre-release requirements discovered transitively, but tin prime different versions than erstwhile uv releases erstwhile some unchangeable and pre-release candidates are available.
You tin opt retired of automatic pre-release action pinch --prerelease disallow. Alternatively, --prerelease let considers pre-releases without first preferring unchangeable releases, and --prerelease definitive only allows them for nonstop requirements that mention a pre-release.
The aged if-necessary-or-explicit mode distinguished betwixt explicitly requested pre-releases and packages pinch nary unchangeable releases. That favoritism is unnecessary now that if-necessary handles some cases, including transitive requirements. The aged sanction remains disposable arsenic an othername but is deprecated and will beryllium removed successful a early release.
Respect --require-hashes directives successful requirements.txt (#19336)
Previously, uv pip instal and uv pip sync warned astir --require-hashes wrong a requirements.txt record but still installed limitations without checking their hashes. Now, the directive enables hash-checking mode, conscionable arsenic if --require-hashes had been passed connected the bid line.
For example, this requirements record is nary longer accepted because the request is neither pinned nor hashed:
You cannot opt retired while the directive is present. Pin each request pinch == and supply its hash, aliases region --require-hashes if hash checking is not intended.
Reject MD5-only hashes successful hash-checking mode (#20758)
Previously, uv pip instal --require-hashes and uv pip sync --require-hashes accepted requirements whose only disposable digest utilized MD5. MD5 is not collision-resistant, truthful relying connected it undermined installations that require hash verification and differed from pip's behavior.
Hash-checking mode now requires astatine slightest 1 unafraid digest for each requirement. For example, the pursuing request is rejected unless a unafraid hash, specified arsenic SHA-256, is besides supplied:
A unafraid hash tin beryllium supplied straight connected the request aliases successful a matching constraints file. Ordinary hash verification without --require-hashes continues to support MD5.
You cannot opt retired while hash checking is required. Regenerate affected hashes pinch SHA-256 aliases different supported unafraid hash.
Reject invalid pylock.toml files and artifacts (#20402, #20440, #20443)
uv now validates further requirements from the pylock.toml specification:
- The packages array must beryllium present. Previously, uv interpreted a missing array arsenic an quiet lockfile, truthful uv pip sync could uninstall an situation alternatively of rejecting malformed input. An explicitly quiet packages = [] array remains valid.
- Lockfile filenames must beryllium pylock.toml aliases a single-name version specified arsenic pylock.dev.toml. Names specified arsenic pylock..toml and pylock.foo.bar.toml are rejected.
- If a wheel, root distribution, aliases different artifact declares a size, the downloaded aliases cached artifact must match. Previously, an incorrect size was accepted erstwhile the hash was correct. Sizes reported by package indexes stay advisory.
You cannot opt retired of these checks. Regenerate malformed lockfiles, rename invalid filenames, and either correct aliases region an incorrect optional size value.
Honor definitive certificate overrides moreover erstwhile nary certificates tin beryllium loaded (#20741, #20767)
Previously, uv ignored SSL_CERT_FILE aliases SSL_CERT_DIR values that pointed to missing aliases inaccessible paths, quiet files aliases directories, aliases sources without valid certificates. Instead, it fell backmost to its default spot roots, perchance allowing HTTPS connections that the configured override was intended to reject.
Now, immoderate non-empty SSL_CERT_FILE aliases SSL_CERT_DIR worth replaces uv's default certificate roots, moreover erstwhile nary valid certificates tin beryllium loaded. In that case, HTTPS requests neglect because nary certificates are trusted. This applies to package downloads and distant scripts, including GitHub Gists.
Fix aliases unset the certificate override. Unsetting it restores the default spot store; quiet environment-variable values proceed to beryllium ignored.
Support pip-compatible --cert handling successful uv pip (#20418)
The uv pip interface now accepts --cert <path>, e.g.:
As successful pip, the provided PEM bundle replaces each different certificate sources for that invocation, including strategy certificates and SSL_CERT_FILE aliases SSL_CERT_DIR. This alteration has nary effect unless you walk --cert. Include the basal certificate authorities successful the bundle.
--cert is only supported by uv pip commands; different uv commands proceed to usage their existing certificate configuration.
Discover projects comparative to the book passed to uv run (#20225)
Previously, uv tally project/script.py discovered its task from the existent directory, moreover erstwhile the book belonged to different project. uv now starts task and workspace find from the script's directory instead.
For example, moving uv tally other-project/script.py now uses other-project and its dependencies. This fixes scripts that antecedently grounded because their ain limitations were not installed, but tin prime a different situation than before.
You tin opt retired of script-relative find by selecting a task explicitly, e.g., uv tally --project . other-project/script.py.
This stabilizes the target-workspace-discovery preview feature.
Require --force earlier clearing a directory that is not a virtual environment (#20225)
uv venv --clear antecedently removed immoderate existing target directory, moreover if it was not a virtual environment. uv emitted a informing but still deleted the directory and its contents. Now, uv refuses to clear directories that do not incorporate a virtual environment.
You tin opt retired of this information cheque by explicitly passing --force, e.g., uv venv --clear --force ./not-a-virtualenv.
This stabilizes the venv-safe-clear preview feature.
Reject --project erstwhile initializing a project (#20225)
--project selects an existing project, truthful it is not meaningful erstwhile initializing a caller one. Previously, uv init --project illustration warned and initialized illustration anyway; if a positional way was besides provided, --project was ignored.
This usage is now an error. Use uv init illustration to initialize a task astatine the requested path, aliases uv init --directory illustration to alteration the moving directory first.
This stabilizes the init-project-flag preview feature.
Reject missing aliases invalid --project paths (#20225)
uv antecedently warned erstwhile --project referred to a missing directory aliases a record different than pyproject.toml, but past attempted to continue. This could nutrient confusing errors later aliases tally against an unintended project.
Now, uv tally --project missing python fails instantly alternatively of continuing. You cannot opt retired of this behavior. Create the directory first aliases prime an existing project. Passing --project path/to/pyproject.toml remains supported and selects the file's genitor directory.
This stabilizes the project-directory-must-exist preview feature.
Skip distributions pinch non-normalized filenames erstwhile publishing (#20225)
Distribution filenames must usage normalized package names and versions. For example, a instrumentality for type 1.01.0 should beryllium named example-1.1.0-py3-none-any.whl, not example-1.01.0-py3-none-any.whl.
Previously, uv people warned astir non-normalized filenames but still attempted to upload them. It now skips the affected wheels and root distributions instead.
You cannot opt retired of this behavior. Rebuild distributions pinch normalized filenames earlier publishing.
This stabilizes the publish-require-normalized preview feature.
Classify Conda environments named guidelines and guidelines by their paths (#20225)
Conda environments named guidelines aliases guidelines were antecedently assumed to beryllium the guidelines Conda environment, moreover erstwhile they were mean kid environments. uv now recognizes kid Conda environments named guidelines aliases guidelines based connected their paths, arsenic it already does for different names.
You tin opt retired of automatic expert action by requesting an expert explicitly pinch --python /path/to/python.
This stabilizes the special-conda-env-names preview feature.
Reject surgery .venv symlinks during situation discovery (#20433)
Previously, uv could disregard a surgery .venv symlink and proceed searching genitor directories for different virtual environment. As a result, commands specified arsenic uv pip instal could unexpectedly modify an unrelated ancestor environment.
uv now stops astatine a surgery .venv symlink and reports its nonstop path. Errors encountered while reference virtual situation metadata, including support failures, are besides reported instantly alternatively of being ignored.
You cannot opt retired of this behavior. Repair aliases region the surgery .venv symlink and correct immoderate permissions that forestall uv from inspecting the environment.
Reinstall matching installed Python spot versions alternatively of upgrading implicitly (#20659)
Before Python upgrades were supported, uv python instal 3.12 --reinstall doubled arsenic a measurement to instal the latest Python 3.12 spot release. Now that --upgrade is available, --reinstall reinstalls the matching spot releases that are already present.
For example, if Python 3.12.6 and 3.12.7 are installed, uv python instal 3.12 --reinstall reinstalls some versions alternatively of installing the latest disposable 3.12 release.
You tin retrieve the erstwhile upgrade behaviour pinch uv python instal 3.12 --upgrade. Combine --upgrade --reinstall to reinstall only the latest patch.
Require --upgrade-group to sanction an existing dependency group (#18957)
Previously, uv fastener --upgrade-group docs silently succeeded moreover if nary docs dependency group existed. uv now validates the requested group against the project, its workspace members, and workspace-level dependency groups.
You cannot opt retired of this behavior. Correct the group sanction aliases adhd it to [dependency-groups]. Legacy tool.uv.dev-dependencies still satisfies --upgrade-group dev.
Resolve comparative indexes and find-links against --directory (#20740)
The --directory action changes the directory successful which uv operates. Previously, comparative scale and find-links paths supplied connected the bid statement were still resolved against the original moving directory.
uv now resolves --index, --default-index, --index-url, --extra-index-url, and --find-links comparative to the directory selected by --directory. For example:
This now uses project/packages alternatively of ./packages successful the original moving directory. Absolute paths and indexes loaded from configuration files are unaffected.
To sphere the erstwhile target, walk an absolute way aliases set the comparative path, e.g., --index ../packages.
Preserve absolute paths provided to uv add (#18402)
uv adhd antecedently converted each section dependency into a project-relative path, moreover erstwhile the original petition utilized an absolute way aliases a literal file:// URL. It now preserves the shape of the petition successful pyproject.toml and uv.lock:
Absolute paths make a task little portable. Use a comparative way to debar signaling an absolute path. URLs containing expanded variables clasp their existing relative-path behavior.
Remove older PyPy distributions that are only disposable arsenic bzip2 archives (#20423)
Older PyPy spot releases that are only distributed arsenic .tar.bz2 archives are nary longer disposable done uv python install. These releases require unsupported bzip2 archives.
The latest PyPy merchandise for each supported Python insignificant type is disposable arsenic a gzip-compressed archive and remains supported. For example, uv python database 3.10 --all-versions still includes the latest PyPy 3.10 release, but older bzip2-only spot releases are omitted.
You cannot opt retired of this behavior. Request a newer PyPy spot merchandise instead.
Omit excluded-package comments erstwhile annotations are disabled (#20085)
uv pip compile --no-annotate suppresses comments describing the generated requirements file. Previously, a footer listing packages excluded pinch --unsafe-package was still included, moreover though annotations were disabled. That footer is now omitted.
You tin retrieve the footer by removing --no-annotate.
The artifacts successful this merchandise person attestations generated pinch GitHub Artifact Attestations. These tin beryllium verified by utilizing the GitHub CLI:
You tin besides download the attestation from GitHub and verify against that directly:
English (US) ·
Indonesian (ID) ·