Skip to content

Prevent NPM version missmatch on release branches #1900

@spliffone

Description

@spliffone

The current build workflows use node-version: lts/krypton as a floating alias in all actions/setup-node steps.

This alias resolves to whichever specific Node.js point-release GitHub distributes at the time the job runs. When that underlying version changes (e.g., a Node.js patch bump ships a newer bundled npm), npm ci --prefer-offline --no-audit --include=optional can fail because:

  1. Lockfile version mismatch — package-lock.json is committed with a lockfileVersion generated by a specific npm major/minor (e.g., npm 11.x.y). If the runner resolves lts/krypton to a Node release bundled with a different npm, npm ci exits with an error like:

    npm error npm ci can only install packages when your package.json and package-lock.json are in sync.
    or (with newer npm):
    npm warn old lockfile The package-lock.json file was created with an older version of npm...

  2. --prefer-offline amplifies the failure — this flag instructs npm to use the local cache as much as possible and avoid network requests. On a cache miss (which is almost guaranteed after a Node version bump because the cache key is tied to the OS + Node version + lock file hash), npm cannot fall back to the registry and the install fails outright instead of degrading gracefully.

  3. engines field mismatch between CI and local — package.json declares "node": "^24.0.0" and "npm": "11" in the engines field, yet lts/krypton resolves to Node.js 22.x in CI. This means CI is running a version that would be rejected by npm install locally, and any engines-strict tooling or postinstall scripts will emit warnings or errors.

Recommenation

  1. Pin an explicit Node.js version aligned with engines e.g. node-version: '24.0.0'
  2. Remove or replace --prefer-offline--prefer-offline is appropriate only when a warm local cache is guaranteed. In CI the cache is keyed on package-lock.json hash and OS; any change invalidates it. Replacing it with --prefer-frozen-lockfile equivalent (npm ci already implies this) or simply omitting the flag is safer: run: npm ci --no-audit --include=optional
    If install speed is a concern, rely on the cache: 'npm' parameter in actions/setup-node (which sets up ~/.npm caching correctly) and let npm fall back to the registry on a miss.

Metadata

Metadata

Assignees

Labels

in-analysisThe topic needs to be analyzed by our team

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions