DevKitHub

Programming

Semver Range Checker — Does This Version Match?

Enter a version and an npm range to see whether it matches, what the range expands to, and — when it does not match — precisely why.

satisfies1.9.0 satisfies ^1.2.3

What the range means

^1.2.3matches
>=1.2.3 and <2.0.0

This tool runs entirely in your browser. Your input is never uploaded, stored or logged.

How it works

Ranges are desugared to plain comparators and shown, because that is usually the answer on its own. A caret becomes a pair of bounds, and which bounds depends on the leading number in a way that surprises people: ^1.2.3 allows anything below 2.0.0, ^0.2.3 allows only 0.2.x, and ^0.0.3 allows nothing but 0.0.3 itself. Below 1.0.0 the specification treats every release as potentially breaking, so the window narrows as the version approaches zero.

The prerelease rule is the reason to have a tool rather than a mental model. A version carrying a prerelease tag satisfies a range only if some comparator in the matching set names the same major.minor.patch and carries a prerelease of its own. So 1.2.4-beta does not satisfy ^1.2.3, even though 1.2.4 plainly does and the beta sits numerically between them. The reasoning is that a prerelease of 1.2.4 is not something anybody asked for by writing ^1.2.3. Written down it is obvious; met in a failing pipeline it is not, and this tool says which comparator excluded it.

Ordering follows the specification exactly, including the parts that are easy to get wrong: numeric prerelease identifiers compare as numbers so beta.11 comes after beta.2, a numeric identifier sorts below an alphanumeric one, and build metadata after a plus sign is ignored entirely when comparing. Every case is checked against npm’s own semver package rather than against this implementation.

Common problems

Every example below is run against this tool in our test suite, so what it says here is what the tool actually does.

That is not a semantic version.

1.2
Why:
A semantic version has all three numbers. A two-part version is valid as a *range* — it means 1.2.x — but not as a version, and the two boxes take different things.
Fix:
Write 1.2.0. In the range box, 1.2 on its own is fine and means >=1.2.0 <1.3.0.

That is not a version or a range operator.

banana
Why:
The range contains a token that is neither a version nor one of the operators. Often a tag name such as "latest" or "next", which npm resolves through the registry rather than by comparison.
Fix:
Use a version range here. Dist-tags are registry lookups and cannot be evaluated offline.

CI installed a beta nobody asked for, or refused to install one that was needed.

Why:
The prerelease rule. A prerelease is only matched by a range that explicitly mentions a prerelease of the same major.minor.patch, which cuts both ways and catches people in both directions.
Fix:
To allow prereleases of a specific version, name one in the range: ^1.2.3-0 allows every 1.2.3 prerelease.

Frequently asked questions

Why does 1.2.4-beta not satisfy ^1.2.3?
Because prereleases are opt-in. A version with a prerelease tag is only matched when a comparator in the range names the same major.minor.patch and is itself a prerelease. A prerelease of 1.2.4 is not something ^1.2.3 asked for.
Why does ^0.2.3 behave differently from ^1.2.3?
Below 1.0.0 the specification treats every release as potentially breaking, so caret narrows: ^0.2.3 allows 0.2.x only, and ^0.0.3 allows nothing but 0.0.3. It widens to the next major only once the major is non-zero.
Does this match npm exactly?
Every case in the test suite was produced by running npm’s own semver package and recording what it returned, so the comparison is against the reference rather than against this code.

Read more about this

Last updated