Cookies
This website uses cookies to improve the user experience, more information on the legal information path.
Notes
0
years
0
mons
0
days
0
hour
0
mins
0
secs
00
This is the background image
4

Possible solution for NPM - Failed to replace env in config: ${NPM_TOKEN}

Quick answer

npm or yarn found an .npmrc file that references an environment variable (NPM_TOKEN) that is not defined in your shell, so it cannot expand it. Either export the variable (export NPM_TOKEN=your_token), or find the .npmrc that references it — in the project root or in your user home directory — and remove the stale entry. Run the install with --verbose to see exactly which .npmrc files are being read.

The error text itself is the giveaway: Failed to replace env in config: ${{NPM_TOKEN}. npm is telling you it tried to substitute an ${...} placeholder and there was nothing to put in its place.

Why it happens

To install a private package from the GitHub registry you point npm at that registry and give it a token. The token lives in an environment variable so it never ends up committed, and the .npmrc references it by name:

.npmrc

@xabierlameiro:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}

When you run npm install or yarn, npm reads that file and expands every ${VAR} against your current environment. If NPM_TOKEN is not set in that shell, it cannot replace the placeholder and aborts — that is the exact error.

The .npmrc files npm actually reads

This is the part that turns a one-minute fix into a two-hour one. npm does not read a single .npmrc; it merges several, and the closest one wins. In order of precedence:

  1. Project: ./.npmrc
  2. User: ~/.npmrc (on Windows, C:\Users\<you>\.npmrc)
  3. Global: $PREFIX/etc/npmrc
  4. npm's built-in config

So a line you added to your home .npmrc months ago is applied to every project you install, even ones that have no idea what NPM_TOKEN is. That is the usual reason the error shows up in a repo you never configured for the GitHub registry.

Common causes, ranked

  • The variable is genuinely not defined in the shell you ran the command from.
  • The .npmrc lives in your home folder, not the project — so it leaks into unrelated installs. This was my case: I had saved it in C:\Users\xabierlameiro\.npmrc, and every project inherited the ${NPM_TOKEN} reference.
  • The variable is set in a GUI app or a different terminal tab that did not inherit the export.
  • In CI, the secret exists but was never exposed to the step's environment.

How I fixed it

First I ran the install in verbose mode to see which files npm was reading:


yarn install --verbose

The log lists the paths it checks for .npmrc, and that is where I saw it was pulling the config from my user folder. I deleted it from the user folder and recreated it in the root of the project, and the error was gone.

If you instead want the token available everywhere, define it rather than removing the reference:


export NPM_TOKEN=your_token # macOS / Linux
setx NPM_TOKEN your_token # Windows, new shells only

npm config ls -l prints the fully merged configuration, which is the fastest way to confirm whether the token was picked up.

Fixing it in CI

The most common place this bites is continuous integration, because the runner is a fresh machine with none of your local exports. The fix is to hand the secret to the step as an environment variable — the same NPM_TOKEN name the .npmrc expects. In GitHub Actions:

workflow.yml

- name: Install dependencies
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm install --legacy-peer-deps

If you generate the .npmrc on the runner instead of committing it, write the auth line straight into the home file before installing:


echo "//npm.pkg.github.com/:_authToken=${NPM_TOKEN}" >> ~/.npmrc
echo "@your-scope:registry=https://npm.pkg.github.com/" >> ~/.npmrc

Same idea in every CI provider: the .npmrc reference and the environment variable have to agree on the name, and the value has to reach the process that runs the install.

Keep the token out of git

One last thing, because it is a mistake I see often. The .npmrc that references ${NPM_TOKEN} is safe to commit: it holds only the name of the variable, not its value. What must never reach git is an .npmrc with the literal token pasted in (_authToken=ghp_...). If you did that, the token is compromised the moment it is pushed — revoke and rotate it in GitHub, do not just delete the file, because git history keeps it. The rule of thumb: an .npmrc that only references env vars is fine to commit and actually helps your teammates; one with real secrets belongs in .gitignore and, better, should not exist.

Whether it happens locally or in a pipeline, the question is always the same: does the shell that runs npm actually have NPM_TOKEN, and is it reading the .npmrc you think it is? Answer those two and the error disappears.