Skip to content

/errors/semver/typeerror-invalid-comparator

TypeError: Invalid comparator: latest (node-semver Range)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
SemVer
exit code
1
versions
semver (npm) 7
os
any

TypeError: Invalid comparator: latest is thrown by the semver package (the one npm uses) when new semver.Range() meets a piece of the range string that is neither an operator nor a version. Each space-separated part of a range is a comparator (>=1.2.3, <2, ^1.4), and latest, foo or a lone - are not. Use semver.validRange() to check a string first; dist-tags like latest must be resolved to a version by the registry, not parsed as a range.

Reproduce it

bash
npm init -y >/dev/null
npm install --silent --no-audit --no-fund semver@7 >/dev/null 2>&1
cat > ranges.js <<'EOF'
const semver = require("semver");
for (const r of ["^1.x", ">=1.2.3 <2", "latest", "1.2.3 - ", ">= 1.0.0 || foo"]) {
  try {
    console.log(JSON.stringify(r), "->", new semver.Range(r).range);
  } catch (e) {
    console.log(JSON.stringify(r), "->", `${e.name}: ${e.message}`);
  }
}
console.log("validRange('latest'):", semver.validRange("latest"));
console.log("satisfies('1.2.3', 'latest'):", semver.satisfies("1.2.3", "latest"));
EOF
node ranges.js

Output

"^1.x" -> >=1.0.0 <2.0.0-0
">=1.2.3 <2" -> >=1.2.3 <2.0.0-0
"latest" -> TypeError: Invalid comparator: latest
"1.2.3 - " -> TypeError: Invalid comparator: -
">= 1.0.0 || foo" -> TypeError: Invalid comparator: foo
validRange('latest'): null
satisfies('1.2.3', 'latest'): false

The convenience functions (validRange, satisfies, maxSatisfying) catch the error and return null or false. Only the Range and Comparator constructors throw, so the error usually comes from your own code or from a tool that builds ranges directly.

Validate before building a Range

js
const semver = require("semver");
function parseRange(input) {
  const r = semver.validRange(input);
  if (r === null) throw new Error(`not a semver range: ${input}`);
  return new semver.Range(r);
}

In package.json, npm accepts a dist-tag ("react": "latest") as a dependency spec because npm resolves the tag through the registry before any semver range logic runs. Code that reads package.json and passes every value to semver.Range has to treat tags, git URLs, file: paths and aliases separately.

Sources