npm Package "bin" Not Executable - Fix EACCES / Permission Denied on CLI in CI
npm marks a package’s declared bin files executable on install and symlinks them into node_modules/.bin. If a bin script lacks the executable bit - lost in a tarball, a Windows checkout, or a copied tree - invoking it fails with permission denied even though the file is present.
What this error means
A CLI installed as a dependency fails with Permission denied when run from node_modules/.bin, or a local package’s own bin cannot execute. The script exists and is correct; it is just not marked executable.
$ ./node_modules/.bin/my-cli
sh: ./node_modules/.bin/my-cli: Permission denied
# or
npm error code 126
npm error command failed: my-cli (permission denied)Common causes
The bin file lost its executable bit
Archiving, a Windows-authored file, or copying a tree without preserving mode can strip the +x bit. Without it, the OS refuses to execute the script.
Running a local bin that was never chmod-ed
A package’s own bin script committed without the executable bit fails when run directly, since npm’s bin-linking relies on the file being executable.
How to fix it
Restore the executable bit
Mark the bin file executable, and run via npm/npx so the shebang is honored.
chmod +x node_modules/.bin/my-cli # or the package's bin source
# better: invoke through npm so .bin resolution applies
npx my-cli
# for your own package, commit the bit:
git update-index --chmod=+x bin/my-cli.jsReinstall so npm re-links bins
- Run a clean
npm ciso npm re-creates.binlinks with correct modes. - Ensure the bin file has a correct shebang (
#!/usr/bin/env node). - Avoid copying node_modules in a way that drops file modes.
How to prevent it
- Commit the executable bit on your package’s bin files.
- Run CLIs via npx / npm scripts, not hard-coded .bin paths.
- Reinstall clean so npm re-links bins with correct modes.