npm cannot rename a temp folder or package because the destination is not writable or the source is locked. Release locks, fix ownership, and use user-owned prefixes before retrying.
Fixes npm ERR! Error: EACCES: permission denied, rename '<from>' -> '<to>'
rm -rf node_modules package-lock.json
sudo rm -rf $(npm config get prefix)/lib/node_modules/.staging 2>/dev/null || truerm -rf node_modules package-lock.jsonsudo rm -rf $(npm config get prefix)/lib/node_modules/.staging 2>/dev/null || truenpm ERR! Error: EACCES: permission denied, rename '<from>' -> '<to>'
npm renames .staging directories into final package folders during install. If the destination is root-owned, read-only, or held open by another process, the rename syscall fails with EACCES and npm aborts. This shows up after mixing sudo and non-sudo installs, on WSL2 with NTFS ACLs, inside Docker/CI when the workspace is root-owned, and on Windows when VS Code/Defender or long-path policy blocks the rename.
rm -rf node_modules package-lock.json
sudo rm -rf $(npm config get prefix)/lib/node_modules/.staging 2>/dev/null || truesudo chown -R $(whoami) .
sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}npm config set cache ~/.npm-cache
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
export PATH="$HOME/.npm-global/bin:$PATH"Close VS Code/terminals, add Defender exclusions for the project and npm cache, and enable Developer Mode to reduce symlink/rename restrictions.
npm cache clean --force
npm cici recreates node_modules from scratch, avoiding partial folders.
Use docker run --user to match host UID/GID or chown the bind-mounted workspace before npm install so rename can replace directories.
On WSL2, working inside /mnt/c uses NTFS ACLs that can block renames; move the repo to the Linux filesystem for consistent POSIX permissions. Long Windows paths can also break renames—keep the project path short. In Docker, bind mounts inherit host ownership; matching UID or chowning the volume prevents EACCES during rename. Avoid mixing sudo and user installs; root-owned .staging directories repeatedly block replacement.