npm "404 Not Found" for a Private Package - Fix in CI
A 404 for a package you know exists usually means npm asked the wrong registry - or asked anonymously, so a private package looks like it does not exist at all.
What this error means
npm install/npm ci fails with 404 Not Found - GET for a scoped/private package, while public packages resolve fine. The package is real; npm is just looking in the wrong place or without credentials.
npm error code E404
npm error 404 Not Found - GET https://registry.npmjs.org/@acme%2finternal-lib
npm error 404 '@acme/internal-lib@^1.2.0' is not in this registry.Common causes
Scope not pointed at the private registry
Without @acme:registry=https://your-registry/, npm queries the public registry for the scoped package and gets a legitimate 404.
Anonymous request to a private registry
Some private registries return 404 (not 401) for unauthenticated reads to avoid leaking existence. No token means the package is invisible.
Typo in the package name or version
A wrong scope, name, or a version that was never published also produces a genuine 404.
How to fix it
Map the scope and authenticate
Point the scope at the right registry and supply a token.
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 ciConfirm the package exists as named
- Double-check the scope, name, and version against the registry.
- Verify the version in the lockfile was actually published.
- If it 404s only in CI, suspect missing scope mapping or token, not a missing package.
How to prevent it
- Always map private scopes to their registry in .npmrc.
- Provide CI tokens for private reads.
- Pin published versions in the lockfile.