GitHub Packages npm "401" (GITHUB_TOKEN read:packages scope) in CI
Installing from GitHub Packages npm returned 401. Either the token has no read:packages scope, or .npmrc does not send an _authToken for the npm.pkg.github.com host.
What this error means
npm install fails with "npm error code E401" and "npm error 401 Unauthorized - GET https://npm.pkg.github.com/@scope%2fpkg" while public registry packages install fine.
npm error code E401
npm error 401 Unauthorized - GET https://npm.pkg.github.com/@acme%2fwidgets - authentication token not providedCommon causes
The token lacks read:packages
A classic PAT needs read:packages; the default GITHUB_TOKEN needs packages: read in the job permissions. Without it, reads are unauthorized.
.npmrc does not route the scope with a token
Without a //npm.pkg.github.com/:_authToken= line and a scope registry mapping, npm sends anonymous requests to GitHub Packages.
How to fix it
Grant read:packages and configure .npmrc
- Add
packages: readto the workflow job permissions (or use a PAT withread:packages). - Map the scope to the registry and set the auth token in
.npmrc. - Re-run the install.
@acme:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}Set job permissions in the workflow
Give the job read access to packages and pass the token as NODE_AUTH_TOKEN.
permissions:
contents: read
packages: read
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}How to prevent it
- Grant
packages: read(or a PAT with read:packages) for installs. - Keep the scope-to-registry mapping and auth token in
.npmrc. - Use
NODE_AUTH_TOKENso the token is not hard-coded.