Skip to content
Latchkey

npm "ENOTEMPTY: directory not empty, rename" - Fix Stale node_modules in CI

npm installs packages by staging them and renaming into place. ENOTEMPTY on that rename means the destination directory already had unexpected contents - a leftover from a stale node_modules, a restored partial cache, or a concurrent process.

What this error means

npm install/npm ci fails with ENOTEMPTY: directory not empty, rename ... pointing at a .staging or package path under node_modules. It often follows a restored cache or an interrupted previous install.

npm output
npm error code ENOTEMPTY
npm error syscall rename
npm error path /app/node_modules/.staging/lodash-XXXX
npm error dest /app/node_modules/lodash
npm error errno -39
npm error Error: ENOTEMPTY: directory not empty, rename '...' -> '...'

Diagnose it: what is different about the runner?

A build that passes locally and fails on a runner differs in a small number of predictable ways. Check those before changing build configuration, because the build config is usually not the thing that changed.

.github/workflows/ci.yml
- run: |
    node --version && npm --version
    echo "NODE_ENV=$NODE_ENV  CI=$CI"
    nproc && free -h && df -h /
    ls -la node_modules/.bin | head

Common causes

A stale or partially populated node_modules

Leftover package directories from an interrupted install (or a restored partial cache) make the destination non-empty when npm tries to rename the staged copy in.

A concurrent process touching node_modules

A watcher, a parallel install, or antivirus holding files under node_modules can leave a directory non-empty at the moment of rename.

How to fix it

Start from a clean node_modules

Remove the existing tree and reinstall so the rename targets are empty.

Terminal
rm -rf node_modules
npm cache verify
npm ci

Remove contention

  1. Ensure no other step, watcher, or process touches node_modules during install.
  2. Do not cache a partial node_modules across runs.
  3. Run installs sequentially, not in parallel, for the same project.

The three that account for most of them

  • Case sensitivity. Linux runners are case sensitive, macOS is not. An import with the wrong case resolves locally and fails in CI.
  • Out of memory. Exit code 137 is a SIGKILL from the kernel, not a build error. Raise --max-old-space-size or use a larger runner.
  • devDependencies pruned. NODE_ENV=production makes npm ci skip devDependencies, so the build tool itself goes missing. Set it after install, not before.

How to prevent it

  • Use npm ci so node_modules starts empty.
  • Never cache or restore a partial node_modules.
  • Avoid concurrent processes touching the module tree.

Frequently asked questions

What causes npm "ENOTEMPTY: directory not empty, rename"?
There are 2 common causes: a stale or partially populated node_modules and a concurrent process touching node_modules. Leftover package directories from an interrupted install (or a restored partial cache) make the destination non-empty when npm tries to rename the staged copy in.
How do I fix npm "ENOTEMPTY: directory not empty, rename"?
There are 2 fixes depending on which cause you have: start from a clean node_modules and remove contention. Work through them in order, since the first is the most common.
What does npm "ENOTEMPTY: directory not empty, rename" actually mean?
npm install/npm ci fails with ENOTEMPTY: directory not empty, rename ...
How do I stop npm "ENOTEMPTY: directory not empty, rename" happening again?
Use npm ci so node_modules starts empty. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card