npm E401 / ENEEDAUTH - Fix Registry Auth and .npmrc Token in CI
E401/ENEEDAUTH means the registry rejected the request for lack of valid credentials. In CI it is almost always a missing or unexpanded auth token in .npmrc for a private or scoped registry.
What this error means
Installing a private/scoped package fails with npm error code E401 (or ENEEDAUTH), saying the auth token is incorrect or missing. Public packages install fine; only the authenticated registry fails.
npm error code E401
npm error Incorrect or missing password.
npm error If you were trying to login, change your password, create an
npm error authentication token or enable two-factor authentication...
npm error need auth for: https://npm.pkg.github.com/@acme/...Common causes
No auth token in CI .npmrc
The token that works on your machine lives in a local ~/.npmrc the CI runner does not have, so authenticated requests come through anonymous and get a 401.
The token env var is not expanded
An .npmrc line like //registry/:_authToken=${NPM_TOKEN} only works if NPM_TOKEN is set in the job env. A missing or misnamed secret leaves the placeholder literal.
The scope is not mapped to the private registry
Without a @scope:registry=... line, npm asks the default registry for the scoped package, which has no idea who you are.
How to fix it
Provide a token-bearing .npmrc in CI
Write the registry mapping and token at job start from a secret.
cat > .npmrc <<'EOF'
@acme:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}
EOF
NODE_AUTH_TOKEN="$REGISTRY_TOKEN" npm ciVerify the secret and scope mapping
- Confirm the secret name in the workflow matches the env var .npmrc expands.
- Ensure each private scope has a
@scope:registry=line. - Check the token has read (and, for publish, write) scope and is not expired.
How to prevent it
- Generate CI .npmrc from a secret, never commit tokens.
- Map every private scope to its registry explicitly.
- Rotate and scope registry tokens to least privilege.