#15025·pnpm

A custom fetch done during resolution is filed under an identity the install pass does not derive, so the hook runs twice

Author: zkochanCreated Sep 17, 2026Updated Sep 17, 2026
Labelstype: bugarea: resolution

pnpm version

12.4.2

Code to reproduce the issue

CustomFetcherSession::completed keys a verified fetch by (package_id, integrity) so that a fetch done during resolution is reused during installation instead of running the hook a second time. The two phases derive package_id differently:

  • Resolution, in PrefetchingResolver, uses ResolvedPackageInfo::name_ver when the resolver filled it and falls back to the tarball URL otherwise.
  • Installation derives the pkg_id from the lockfile entry, which for a registry-shaped package is name@version.

A resolver that leaves name_ver unset — every pnpmfile resolvers hook does, see CustomResolverAdapter::resolved_hook_result — therefore files its entry under the URL while the install pass looks it up under name@version. The lookup misses and the custom fetcher runs again.

Expected behavior

One custom fetch per package per install.

Actual behavior

Two, whenever the resolve-time custom fetch path runs for a resolver result with no name_ver.

Additional information

Noticed in review of #15013. The mismatch predates that PR — populate_missing_integrity already used the same fallback — but it only applied to tarballs with no integrity. #15013 also reads an already-pinned archive when the resolver supplied no manifest, so more resolutions now take the path.

The remedy is to make the two phases agree on one identity. Registering the completed fetch under the name@version read from the fetched manifest is the smaller version of that; the durable version is a single resolution-plus-integrity identity both phases derive. Either way it needs a pnpmfile declaring both a resolvers and a fetchers hook to test, which is why it was not carried in that PR.

Related: #15021 is the same shape of defect in the tarball mem cache, where resolve-time publication and install-time lookup disagree about what identifies an extraction.

Node.js version

24.18.1

Operating System

macOS


Written by an agent (Claude Code, claude-opus-5).