10aday › Version Constraint Checker › Pre-release versions (beta, rc)
^1.2.0 match 1.3.0-beta? Pre-release versions in five package managersShort answer: no, not by default. All five package managers skip pre-releases (-beta, -rc, b1, .rc1) unless you ask for them.
But “asking” works differently in each one. Put a pre-release in the constraint, and npm and Cargo only open the door for that exact x.y.z. Composer, pip and RubyGems then accept any newer pre-release.
And in RubyGems, < 2 lets 2.0.0.rc1 through.
Have a constraint and a list of versions? Paste them into the Version Constraint Checker: it shows, side by side, what npm, Cargo, Composer, pip and RubyGems accept.
Suppose the package has published three versions: 1.2.5, 1.3.0-beta.1 and 2.0.0-rc.1 (written in each tool's own syntax). Each cell shows the constraint and the version the tool picks. Highlighted cells are where one tool behaves differently from the others.
| Constraint | npm | Cargo | Composer | pip | RubyGems |
|---|---|---|---|---|---|
| ^1.2.0 (or its equivalent) | ^1.2.0→ 1.2.5 | ^1.2.0→ 1.2.5 | ^1.2.0→ 1.2.5 | >=1.2.0,<2→ 1.2.5 | ~> 1.2→ 1.2.5 |
| >=1.0.0 | >=1.0.0→ 1.2.5 | >=1.0.0→ 1.2.5 | >=1.0.0→ 1.2.5 | >=1.0.0→ 1.2.5 | >= 1.0.0→ 1.2.5 |
| ^1.2.0-beta.1 (a pre-release in the constraint) | ^1.2.0-beta.1→ 1.2.5 | ^1.2.0-beta.1→ 1.2.5 | ^1.2.0-beta1→ 1.3.0-beta1 | >=1.2.0b1,<2→ 1.3.0b1 | >= 1.2.0.beta1, < 2→ 2.0.0.rc1 |
| >=2.0.0-rc.1 | >=2.0.0-rc.1→ 2.0.0-rc.1 | >=2.0.0-rc.1→ 2.0.0-rc.1 | >=2.0.0-RC1→ 2.0.0-RC1 | >=2.0.0rc1→ 2.0.0rc1 | >= 2.0.0.rc1→ 2.0.0.rc1 |
| ^1.3.0-beta.1 | ^1.3.0-beta.1→ 1.3.0-beta.1 | ^1.3.0-beta.1→ 1.3.0-beta.1 | ^1.3.0-beta1→ 1.3.0-beta1 | >=1.3.0b1,<2→ 1.3.0b1 | >= 1.3.0.beta1, < 2→ 2.0.0.rc1 |
| >1.2.5 (only pre-releases are newer) | >1.2.5→ nothing | >1.2.5→ nothing | >1.2.5→ nothing | >1.2.5→ 2.0.0rc1 | > 1.2.5→ nothing |
Tested on 2026-11-12 with node-semver (npm's resolver library), the Cargo rules of the semver crate, a real composer update (Composer 2.8, default minimum-stability), Python packaging 26.3 (the library pip uses) and RubyGems 3.5.22.
Pip and Composer also look at other packages and options; this is the default case with one dependency.
major.minor.patch. So >=2.0.0-rc.1 accepts 2.0.0-rc.2, but never 2.1.0-beta.1.major.minor.patch.^1.2.0 means ≥1.2.0.0-dev). It is minimum-stability, stable by default, that filters them out. A flag such as @beta, or a -beta1 in the constraint, lowers it for that package.--pre, or only pre-releases match. <2.0 never matches 2.0rc1.--pre. Once they are allowed, plain version order applies: 2.0.0.rc1 is below 2.| Tool | Get the release candidate of 2.0 |
|---|---|
| npm | "^2.0.0-rc.1" in package.json |
| Cargo | "2.0.0-rc.1" in Cargo.toml (a bare version is a caret requirement) |
| Composer | "^2.0@RC", or "^2.0.0-RC1" |
| pip | pip install --pre pkg, or pkg>=2.0.0rc1 |
| RubyGems | gem install pkg --pre, or gem "pkg", ">= 2.0.0.rc1" in the Gemfile |
To see how each tool orders 1.0.0-1, 1.0.0rc1 or 1.0.0.beta against the final release, paste them into the Version sorter.
No. In npm a pre-release only matches if the range itself contains a pre-release on the same major.minor.patch. ^1.2.0-beta.1 matches 1.2.0-beta.2 but still not 1.3.0-beta.1. Cargo follows the same rule.
npm and Cargo: write it in the constraint, e.g. ^2.0.0-rc.1. Composer: ^2.0@RC, a constraint with -RC1, or "minimum-stability". pip: pip install --pre or a specifier that names a pre-release, e.g. >=2.0.0rc1. RubyGems: gem install --pre or a requirement such as >= 2.0.0.rc1.
pip accepts a pre-release when no final release satisfies the specifier. With 1.2.5 and 2.0.0rc1 published, >1.2.5 installs 2.0.0rc1. Composer, npm, Cargo and RubyGems install nothing in that case.
Not in npm, Cargo, Composer or pip (PEP 440 says <V excludes pre-releases of V). In RubyGems, 2.0.0.rc1 sorts below 2.0.0, so < 2 accepts it as soon as pre-releases are allowed.
Writing -beta1 in a root requirement sets the stability for that package to beta. Every beta in the range is then allowed, and Composer takes the highest one. Use "prefer-stable": true to keep stable releases when one fits.
^ and ~ into [project] dependencies (Poetry 2, uv)