You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Why does >1.2 throw as an invalid comparator? #802
I am trying to understand why npx -r '>1.2' 1.2.8 results in 1.2.8 not satisfying the range. I think >1.2 should expand to >1.2.0 <1.3.0 which would mean 1.2.8 satisfies. But stepping through the tool, I see it hits this path:
I'm just not seeing the rule you're basing that on. If the readme isn't the source of truth for the expansion rules, please point me to the right document.
It’s not documented that i can see, but it’s common sense - would “1.2” be satisfied by 1.2.99? Obviously yes, because it’s a range, not a short way to express one version.
Sorry, you've just confused me even more. I originally asserted that 1.2.8 should satisfy >1.2. Your response was that it shouldn't. Now you're suggesting it should.
This discussion will continue for years until there's an npm specification :)
@jsumners ,
As you, I'm surprised me because I thought semver.coerce() was being applied before the comparison.
Then I reasoned that it was checking for inclusion in a set, so the logical thing to do was to convert '1.2' to '1.2.x' and not coerce to '1.2.0' (the same for 1 to 1.x.x).
After that, the results in this list made perfect sense to me...
semver.satisfies('1.2.0','1')// true -- '1' is converted to '1.x.x'semver.satisfies('1.2.0','1.2')// true -- '1.2' to '1.2.x' an so onsemver.satisfies('1.2.0','1.2.0')// truesemver.satisfies('1.2.0','=1.2')// true -- The '=' makes no differencesemver.satisfies('1.2.0','=1.2.0')// truesemver.satisfies('1.2.0','~1.2')// true -- '~#.#' is equal to '#.#.x'semver.satisfies('1.2.0','~1.2.0')// truesemver.satisfies('1.2.0','<1.2')// falsesemver.satisfies('1.2.0','<1.2.0')// falsesemver.satisfies('1.2.0','<=1.2')// truesemver.satisfies('1.2.0','<=1.2.0')// truesemver.satisfies('1.2.0','>1.2')// falsesemver.satisfies('1.2.0','>1.2.0')// falsesemver.satisfies('1.2.0','>=1.2')// truesemver.satisfies('1.2.0','>=1.2.0')// truesemver.satisfies('1.2.0','^1.2')// truesemver.satisfies('1.2.0','^1.2.0')// true -- '^#.#' is equal to '#.x.x'
@ljharb does this list of rules look correct to you?
A version string with all three primary positions provided specifies an exact version, e.g. 1.2.3 is equivalent to =1.2.3.
A version string with only one or two primary positions provided equates to an X-range, e.g 1.2 is equivalent to 1.2.x is equivalent to >=1.2.0 <1.3.0 and 1 is equivalent to 1.x.x is equivalent to >=1.0.0 <2.0.0.
A version string prefixed with any primitive (< | > | >= | <= | =) is not an X-range and only the positions provided count, e.g >1.2.3 is equivalent to >=1.2.4, >1.2 is equivalent to >=1.3.0, and >1 is equivalent to >=2.0.0.
Tilde and Caret range expansions are described fully in the readme.
A version string with all three primary positions provided specifies an exact version, e.g. 1.2.3 is equivalent to =1.2.3.
yes
A version string with only one or two primary positions provided equates to an X-range, e.g 1.2 is equivalent to 1.2.x is equivalent to >=1.2.0 <1.3.0 and 1 is equivalent to 1.x.x is equivalent to >=1.0.0 <2.0.0.
right
A version string prefixed with any primitive (< | > | >= | <= | =) is not an X-range and only the positions provided count, e.g >1.2.3 is equivalent to >=1.2.4, >1.2 is equivalent to >=1.3.0, and >1 is equivalent to >=2.0.0.
In the context of semver.satisfy() all the shortened versions are X-ranges.
That's why it's better to use the full version with comparison operators, as in this example from eslint's package.json.
@aMarCruz thank you for the information. I am not concerned with the various methods exported by this module. I am solely concerned with how strings are meant to be parsed and interpreted. In that regard, your example for semver.satisfy is covered by the fourth "rule," not the third one.
Activity
ljharb commentedon Aug 27, 2025
>1.2does not expand to>1.2.0, it equates to>= 1.3. In other words,> 1.2means that no 1.2.x version can satisfy it.jsumners commentedon Aug 28, 2025
I see. Thank you.
jsumners commentedon Aug 28, 2025
Sorry, I'm reopening this. I think this line is confirming your answer @ljharb:
node-semver/README.md
Lines 164 to 166 in d17aebf
But further down we have:
node-semver/README.md
Lines 316 to 321 in d17aebf
This seems to be a conflict to me.
wraithgar commentedon Aug 28, 2025
1.2is not the same as>1.2jsumners commentedon Aug 28, 2025
1.2is a component of>1.2. The version string should still expand the same.ljharb commentedon Aug 28, 2025
1.2does not expand to1.2.0. It expands to1.2.x, and>1.2.xindeed excludes any 1.2.jsumners commentedon Aug 28, 2025
Which expands to
1.2.0. Thus,>1.2should expand to>1.2.0, right?ljharb commentedon Aug 28, 2025
No, it does not expand to 1.2.0. It can't expand without a concrete list of existing versions, and it will always match the latest 1.2, not the .0
jsumners commentedon Aug 28, 2025
I'm just not seeing the rule you're basing that on. If the readme isn't the source of truth for the expansion rules, please point me to the right document.
ljharb commentedon Aug 28, 2025
It’s not documented that i can see, but it’s common sense - would “1.2” be satisfied by 1.2.99? Obviously yes, because it’s a range, not a short way to express one version.
jsumners commentedon Aug 29, 2025
Sorry, you've just confused me even more. I originally asserted that 1.2.8 should satisfy >1.2. Your response was that it shouldn't. Now you're suggesting it should.
ljharb commentedon Aug 30, 2025
1.2.8certainly satisfies1.2. It certainly does not satisfy>1.2(which is the same as>= 1.3).aMarCruz commentedon Sep 1, 2025
This discussion will continue for years until there's an npm specification :)
@jsumners ,
As you, I'm surprised me because I thought
semver.coerce()was being applied before the comparison.Then I reasoned that it was checking for inclusion in a set, so the logical thing to do was to convert
'1.2'to'1.2.x'and not coerce to '1.2.0' (the same for1to1.x.x).After that, the results in this list made perfect sense to me...
...as this...
satisfiesdoes not work as other semver methods ...gt,lt, etc.The conclusión is to use the full semver (n.n.n) if you're unsure.
This is the gist with the source
jsumners commentedon Sep 1, 2025
@ljharb does this list of rules look correct to you?
1.2.3is equivalent to=1.2.3.1.2is equivalent to1.2.xis equivalent to>=1.2.0 <1.3.0and1is equivalent to1.x.xis equivalent to>=1.0.0 <2.0.0.< | > | >= | <= | =) is not an X-range and only the positions provided count, e.g>1.2.3is equivalent to>=1.2.4,>1.2is equivalent to>=1.3.0, and>1is equivalent to>=2.0.0.ljharb commentedon Sep 1, 2025
There's some nuance you're missing about prereleases, but otherwise that sounds correct.
aMarCruz commentedon Sep 2, 2025
yes
right
In the context of
semver.satisfy()all the shortened versions are X-ranges.That's why it's better to use the full version with comparison operators, as in this example from eslint's package.json.
{ "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }See the output of
semver.toComparators('^18.18.0 || ^20.9.0 || >=21.1.0')...Saludos desde México.
ljharb commentedon Sep 2, 2025
Indeed,
^18.8and^18.8.0are identical. (typically the shorter one is preferred)jsumners commentedon Sep 2, 2025
@aMarCruz thank you for the information. I am not concerned with the various methods exported by this module. I am solely concerned with how strings are meant to be parsed and interpreted. In that regard, your example for
semver.satisfyis covered by the fourth "rule," not the third one.mbtools commentedon Jun 20, 2026
>1.2means "greater than any 1.2 version". Therefore,1.2.8does not satisfy the range.Works as designed. Let's close it.