Files
pnpm/.changeset/empty-version-range-resolves.md
T
Felipe PletsandZoltan Kochan f2fa9c953b fix(resolver): treat an empty version range as "*" (#13674)
An omitted version range means "any version" in JS semver, but the Rust
port classified it as a dist-tag: Version::parse and Range::parse both
reject "", and is_valid_dist_tag("") is vacuously true. The picker then
asked the registry for a tag that cannot exist, so any manifest
publishing an empty range -- js-xlsx, codepage and ssf all do -- failed
to install.

Add a semver_range shim to resolving-resolver-base modelling the two
readings of semver.validRange that pnpm relies on, and route each call
site to the one its TypeScript counterpart uses.

is_any_version_range models the loose reading, validRange(x, true) ===
"*", which is the mode version-selector-type runs in. It answers before
Version::parse and Range::parse in both selector classifiers, so an
omitted range normalizes to "*" instead of falling through to the
dist-tag branch. Running first also fixes "^1.0.0 || ", which
Range::parse otherwise accepts and silently narrows to "^1.0.0". The
same gap had been dropping empty specs out of the preferred-versions
tie-break table.

is_valid_semver_range models the strict reading, validRange(x) != null,
under which one unparsable comparator set invalidates the whole union.
It replaces the two Range::parse(..).is_ok() checks that disambiguate a
version range from a package name. These cannot use the loose reading:
"npm:is-negative@^2 || " would take the range branch, dropping the inner
name so the outer alias becomes the package name, and pnpm would install
whatever is published under it.

Verified against pnpm 11.20.0 rather than by reading source: the
empty-range repro and the union case both produce byte-identical
lockfiles.

Fixes pnpm/pnpm#13673.

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-08-06 11:34:23 +02:00

413 B

pacquet
pacquet
patch

Dependencies declared with an empty version range ("adler-32": "") install again instead of failing with ERR_PNPM_NO_MATCHING_VERSION #13673. An omitted range means "any version", as it does in npm and pnpm v11, so packages that publish one — such as js-xlsx, codepage, and ssf — no longer need an overrides entry to install.