GitHub Actions Caching node_modules Still Reinstalls Everything
Caching node_modules does not speed up the build because npm ci deletes node_modules before installing, or because a restored node_modules is not trusted. Caching the package-manager download cache plus npm ci is the reliable pattern.
What this error means
A node_modules cache restores successfully but the install step still does full work, so the cache adds upload/download time without saving install time.
# node_modules restored, then:
- run: npm ci # npm ci removes node_modules and reinstalls anywayCommon causes
npm ci wipes node_modules
npm ci deletes node_modules before installing for a clean, reproducible tree, so a cached node_modules is discarded and provides no benefit.
Restored tree not actually reused
Tools and lockfile changes can invalidate a restored node_modules, and a partial restore can be slower or riskier than a clean install.
How to fix it
Cache the download cache, run npm ci
Cache ~/.npm keyed on the lockfile and run npm ci - the install reuses cached tarballs but still produces a clean tree fast.
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
- run: npm ciOr use setup-node built-in caching
- Set cache: npm on actions/setup-node to cache the download cache automatically.
- Keep running npm ci for a reproducible install.
- Only cache node_modules directly if you also use npm install (not ci) and key strictly on the lockfile.
How to prevent it
- Cache ~/.npm (the download cache), not node_modules, with npm ci.
- Use setup-node cache: npm for the common case.
- Key the cache on the committed lockfile hash.