| name | lockfile-regen |
| description | Force-regenerate a stale `package-lock.json` (or pnpm-lock.yaml, yarn.lock, bun.lockb). The pattern when: `npm ci` fails with `Invalid: lock file's pkg@x.y.z does not satisfy pkg@x.y.z` after a package.json bump, or when CI keeps installing the wrong dep version. Covers: `--save-exact` to pin versions, `--package-lock-only` to avoid disk-space issues, `--legacy-peer-deps` for @capacitor peer conflicts, and the common "npm resolves ^7.8.0 to 5.22.0" trap. |
Lockfile Regeneration
When npm ci fails with Invalid: lock file's pkg@x.y.z does not satisfy pkg@x.y.z, the fix is to regenerate the lockfile. This skill covers the standard recipe.
The Trigger
You need this skill when:
- Bumped
prisma to ^7.8.0 but CI still uses 5.22.0
- Added a new devDependency (e.g.,
@eslint/js) but the lockfile doesn't have it
- Two deps in
package.json have peer-dep conflicts that the existing lockfile doesn't account for
- Switching from npm to pnpm (or vice versa) and need a fresh lockfile
The Recipe (npm)
cd /tmp/<repo>
rm package-lock.json
rm -rf node_modules
npm install [new-deps-if-any] --save-exact --package-lock-only --ignore-scripts
Flag-by-flag:
--save-exact: pins the version without ^ (so 7.8.0 not ^7.8.0)
--package-lock-only: updates the lockfile without running install scripts
--ignore-scripts: prevents postinstall hooks (e.g., prisma generate) from running during the lockfile update
--legacy-peer-deps: needed for repos with peer-dep conflicts (e.g., @capacitor)
The "npm resolves ^7.8.0 to 5.22.0" Trap
^7.8.0 means >=7.8.0 <8.0.0. But sometimes npm's hoisting algorithm pins it to a lower version because of other constraints. Common case: bumping prisma to ^7.8.0 and the existing @prisma/client@^5.22.0 pulls prisma back to 5.22.0 via dedup.
Fix: pin the exact version. Don't use ^7.8.0 — use 7.8.0:
{
"dependencies": {
"@prisma/client": "7.8.0"
},
"devDependencies": {
"prisma": "7.8.0"
}
}
Then npm install --save-exact will respect the pin.
pnpm
pnpm install --lockfile-only
rm pnpm-lock.yaml
pnpm install --lockfile-only
pnpm's lockfile is generally more reliable than npm's. If pnpm-lock is out of sync, the fix is usually to delete and regenerate.
yarn (classic)
rm yarn.lock
rm -rf node_modules
yarn install
yarn doesn't have a "lockfile-only" mode in v1, so you have to do a full install (which is what you usually want anyway with yarn).
bun
rm bun.lockb bun.lock
bun install
Bun is the newest. Its lockfile is more reliable than npm's but newer.
Disk Space Gotcha
Regenerating a lockfile with npm install (not --package-lock-only) installs node_modules, which can be 500MB-1GB per repo. If you're working on a fleet, you don't have the disk space to install for 5+ repos in parallel.
Fix: always use --package-lock-only for fleet operations. It updates the lockfile without installing the actual packages. The CI runner has its own clean install.
If you do need to actually install (to verify the lockfile works), limit to 2-3 repos in parallel and rm -rf node_modules between batches.
Verification
git diff package-lock.json | head -50
jq -r '.packages["node_modules/<dep>"].version' package-lock.json
rm -rf node_modules
npm ci
Related Skills & Chains
prisma-fleet-migration — The most common trigger for needing this skill. Bumping prisma to 7 needs a forced lockfile regen.
eslint-flat-config-upgrade — Bumping eslint to 9 + adding new plugins (e.g., @eslint/js, typescript-eslint) needs the same regen.
fleet-ci-audit — Identifies which repos in the fleet have lockfile-related failures.