From d3a0765beaaa1ba3ab2a116e1efc7b1f54821ddc Mon Sep 17 00:00:00 2001 From: Ishan Gupta <141325549+chocothunder5013@users.noreply.github.com> Date: Fri, 27 Feb 2026 21:58:55 +0530 Subject: [PATCH] fix(dependencies-hierarchy): handle undefined `pkgSnapshot` in `pnpm why -r` (#10705) * fix(dependencies-hierarchy): handle undefined pkgSnapshot in pnpm why -r Running pnpm why -r crashes with TypeError due to undefined pkgSnapshot during invokation of pkgSnapshotToResolution. This commit wraps resolution and integrity steps with if (pkgSnapshot). Also, added unit test for the same. close #10700 * fix: handle undefined pkgSnapshot in pnpm why -r * Apply suggestions from code review #10700 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Zoltan Kochan Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .changeset/famous-cloths-press.md | 6 ++++ .../dependencies-hierarchy/src/getPkgInfo.ts | 14 ++++---- .../test/getPkgInfo.test.ts | 33 +++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 .changeset/famous-cloths-press.md create mode 100644 reviewing/dependencies-hierarchy/test/getPkgInfo.test.ts diff --git a/.changeset/famous-cloths-press.md b/.changeset/famous-cloths-press.md new file mode 100644 index 0000000000..4ee116265c --- /dev/null +++ b/.changeset/famous-cloths-press.md @@ -0,0 +1,6 @@ +--- +"@pnpm/reviewing.dependencies-hierarchy": patch +"pnpm": patch +--- + +Handle undefined pkgSnapshot in `pnpm why -r` [#10700](https://github.com/pnpm/pnpm/issues/10700). diff --git a/reviewing/dependencies-hierarchy/src/getPkgInfo.ts b/reviewing/dependencies-hierarchy/src/getPkgInfo.ts index 16b062b06f..f2f999a310 100644 --- a/reviewing/dependencies-hierarchy/src/getPkgInfo.ts +++ b/reviewing/dependencies-hierarchy/src/getPkgInfo.ts @@ -68,7 +68,7 @@ export function getPkgInfo (opts: GetPkgInfoOpts): { pkgInfo: PackageInfo, readM let integrity: string | undefined const depPath = refToRelative(opts.ref, opts.alias) if (depPath) { - let pkgSnapshot!: PackageSnapshot + let pkgSnapshot: PackageSnapshot | undefined if (opts.currentPackages[depPath]) { pkgSnapshot = opts.currentPackages[depPath] const parsed = nameVerFromPkgSnapshot(depPath, pkgSnapshot) @@ -87,12 +87,14 @@ export function getPkgInfo (opts: GetPkgInfoOpts): { pkgInfo: PackageInfo, readM isMissing = true isSkipped = opts.skipped.has(depPath) } - resolved = (pkgSnapshotToResolution(depPath, pkgSnapshot, opts.registries) as TarballResolution).tarball - depType = opts.depTypes[depPath] - optional = pkgSnapshot.optional - if ('integrity' in pkgSnapshot.resolution) { - integrity = pkgSnapshot.resolution.integrity as string + if (pkgSnapshot) { + resolved = (pkgSnapshotToResolution(depPath, pkgSnapshot, opts.registries) as TarballResolution).tarball + optional = pkgSnapshot.optional + if ('integrity' in pkgSnapshot.resolution) { + integrity = pkgSnapshot.resolution.integrity as string + } } + depType = opts.depTypes[depPath] } else { name = opts.alias version = opts.ref diff --git a/reviewing/dependencies-hierarchy/test/getPkgInfo.test.ts b/reviewing/dependencies-hierarchy/test/getPkgInfo.test.ts new file mode 100644 index 0000000000..cf79a4e087 --- /dev/null +++ b/reviewing/dependencies-hierarchy/test/getPkgInfo.test.ts @@ -0,0 +1,33 @@ +import { getPkgInfo, type GetPkgInfoOpts } from '../src/getPkgInfo.js' +import path from 'path' + +test('getPkgInfo handles missing pkgSnapshot without crashing', () => { + const opts: GetPkgInfoOpts = { + alias: 'missing-pkg', + ref: 'missing-pkg@1.0.0', + currentPackages: {}, + wantedPackages: {}, + depTypes: {}, + skipped: new Set(), + registries: { + default: 'https://registry.npmjs.org/', + }, + virtualStoreDirMaxLength: 120, + modulesDir: '', + linkedPathBaseDir: '', + } + + const result = getPkgInfo(opts) + + expect(result.pkgInfo).toEqual({ + alias: 'missing-pkg', + name: 'missing-pkg', + version: 'missing-pkg@1.0.0', + isMissing: true, + isPeer: false, + isSkipped: false, + path: path.join('.pnpm/missing-pkg@1.0.0/node_modules/missing-pkg'), + }) + expect(result.pkgInfo.resolved).toBeUndefined() + expect(result.pkgInfo.optional).toBeUndefined() +})