Skip to content
Latchkey

npm .npmrc Auth Token in CI - Configure Registry Credentials Safely

Private installs need an _authToken in .npmrc. In CI the token must come from a secret and the variable in .npmrc must actually expand, or npm sends the literal placeholder and auth fails.

What this error means

Private package installs fail with 401/403, or npm sends the unexpanded token placeholder verbatim because the .npmrc variable was never expanded by the shell or by npm config.

npm
npm ERR! code E401
npm ERR! 401 Unauthorized - GET https://registry.npmjs.org/@acme%2fui
npm ERR! authToken in .npmrc: ${NPM_TOKEN}  (not expanded)

Diagnose it: which registry, and with what credentials?

Registry errors are resolved in a precedence chain, and the effective value is rarely the one in the file you are looking at. Scoped registries, .npmrc files at several levels, and environment variables all combine before a request is made.

Terminal
# the effective, fully merged configuration
npm config list -l | grep -E "registry|_auth|always-auth"

# where each value came from
npm config get registry
npm config get @yourscope:registry

# prove the token works, independently of the install
curl -sI -H "Authorization: Bearer $NPM_TOKEN" \
  "$(npm config get registry)@yourscope%2fpackage" | head -1

Common causes

The token variable was not expanded

A committed .npmrc referencing an env-var token is only expanded when the value is written via the shell or npm config sees the env var; otherwise the literal placeholder string is sent.

No token secret is available in CI

The workflow never injects the token, so .npmrc has no usable credential.

How to fix it

Write the token from a secret at runtime

  1. Expose the token as an env var from a secret.
  2. Write the expanded value into .npmrc before install.
Terminal
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> .npmrc

Pass the secret through the env

  1. Reference the repo secret in the step env block.
  2. Never commit the raw token to .npmrc.
Workflow
env:
  NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

How to prevent it

  • Keep the token in CI secrets, write or expand it into .npmrc at runtime, and add .npmrc token lines to .gitignore so a credential never lands in source control.

Frequently asked questions

What causes npm .npmrc auth token in CI?
There are 2 common causes: the token variable was not expanded and no token secret is available in ci. A committed .npmrc referencing an env-var token is only expanded when the value is written via the shell or npm config sees the env var; otherwise the literal placeholder string is sent.
How do I fix npm .npmrc auth token in CI?
There are 2 fixes depending on which cause you have: write the token from a secret at runtime and pass the secret through the env. Work through them in order, since the first is the most common.
What does npm .npmrc auth token in CI actually mean?
Private package installs fail with 401/403, or npm sends the unexpanded token placeholder verbatim because the .npmrc variable was never expanded by the shell or by npm config.
How do I stop npm .npmrc auth token in CI happening again?
Keep the token in CI secrets, write or expand it into .npmrc at runtime, and add .npmrc token lines to .gitignore so a credential never lands in source control.

Related guides

References

This is a registry failure, not a bug in your code. Latchkey detects, repairs, and retries it for you. Start free → 30-day trial · No credit card