[BUG] Incorrect resolution for missing resolved-entries with non-empty registry path
Is there an existing issue for this?
- [x] I have searched the existing issues
This issue exists in the latest npm version
- [x] I am using the latest npm
Current Behavior
In our ci setup we have an internal registry.npmjs.org mirror which is available via https address with a base prefix, i.e. our local .npmrc files usually feature
registry=https://ci.host/repository/npm/
Now, when running npm i -ddd with no lock file present, everything works as expected, the logs show requests like
npm http fetch GET 200 https://ci.host/repository/npm/qs
and a package-lock.json files is created and populated with entries like
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz"
However, when a resolved-entry is missing in the package-lock.json file (which can happen due to e.g. https://github.com/npm/cli/issues/4263, which I can reproduce locally with npm 11.6), the repository path is not being calculated correctly and npm ci fails with
npm error 404 Not Found - GET https://ci.host/ansi-styles/-/ansi-styles-4.3.0.tgz
I'm not sure about the exact source of this behaviour -- all I can say at this moment is that I see different values arriving in pacote/lib/remote.js at the line
this.resolved = new URL(resolvedURL.pathname, this.registry).href
When running npm i without the lock file, the pathname contains extracted registry address prefix, while with package-lock.json present, it does not.
Expected Behavior
Missing entries should get resolved to correct registry address, i.e. https://ci.host/repository/npm/ansi-styles/-/ansi-styles-4.3.0.tgz in place of https://ci.host/ansi-styles/-/ansi-styles-4.3.0.tgz above.
Steps To Reproduce
In an empty dir, create simple package file
cat > package.json
{
"dependencies": {
"yn": "^5.1.0",
"zwitch": "^2.0.4"
}
}
^D
then run
# install packages as usual
npm i
# trigger vanishing resolved-entry via #4263
# (alternatively, simply remove a resolved entry from the lock file)
rm -r node_modules/yn package-lock.json
npm i
# the error is also present if this is done as first step;
# repository needs to be available under the path for wrong address to show
echo registry=https://ci.host/repository/npm/ > .npmrc
# witness incorrect resolution
rm -r node_modules
npm ci --ddd
# throws, using incorrect path
# ...
# npm silly audit bulk request { yn: [ '5.1.0' ], zwitch: [ '2.0.4' ] }
# npm silly packumentCache corgi:https://ci.host/repository/npm/zwitch cache-miss
# npm http cache yn@https://ci.host/repository/npm/yn/-/yn-5.1.0.tgz 1ms (cache hit)
# npm http fetch GET 200 https://ci.host/repository/npm/zwitch 323ms (cache revalidated)
# npm silly packumentCache corgi:https://ci.host/repository/npm/zwitch set size:15580 disposed:false
# npm http fetch GET 404 https://ci.host/zwitch/-/zwitch-2.0.4.tgz 57ms (cache skip)
# npm verbose stack HttpErrorGeneral: 404 Not Found - GET https://ci.host/zwitch/-/zwitch-2.0.4.tgz
# ...
# npm error 404 Not Found - GET https://ci.host/zwitch/-/zwitch-2.0.4.tgz
# ...
Environment
- npm: 11.6.1, 11.6.2, 10.9.4
- Node.js: 24.11.0
- OS Name: Linux
- npm config:
; "project" config from /home/username/npm-test/.npmrc
fund = false
registry = "https://ci.host/repository/npm/"
; "cli" config from command line options
long = true