npm tried to write ~/.npm or a global prefix it doesn't own — usually after running npm once with sudo. The fix is ownership, not more sudo.
sudo npm install once and parts of ~/.npm (or the global prefix) become root's. Every later non-sudo npm run trips over them. ls -la ~/.npm shows the ownership takeover.
npm prefix -g defaults to /usr/lib on some distros — a root-owned tree. Install globals to your own directory instead of fighting it with sudo.
sudo chown -R $(whoami):$(id -gn) ~/.npm ~/.config 2>/dev/null
mkdir -p ~/.npm-global && npm config set prefix '~/.npm-global' && echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.bashrc
npm cache clean --force 2>/dev/null || sudo npm cache clean --force
npm install -g typescript && which tsc
Never sudo npm install (any flavor): it solves today's EACCES by creating tomorrow's. Fix ownership once, configure prefix once. nvm sidesteps the entire class of problem — everything lives under your own home dir.
Root ran as you but wrote files as root: cache entries, lock files, and global packages became root-owned. Your next unprivileged run hits EACCES on exactly those paths.
Set the global prefix to a shared root-owned location deliberately, install via sudo npm install -g with your eyes open — or better, run the tool via its docker image. But for single-user servers, the home-dir prefix is the clean path.
Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.
Browse the template store →One-time. Yours to modify. Instant download from the NinjaOps template store.