Skip to content

Commit aab72e9

Browse files
committed
fix(arborist): Add better error message when lockfile is malformed
1 parent fdc3413 commit aab72e9

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

workspaces/arborist/lib/arborist/load-virtual.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@ module.exports = cls => class VirtualLoader extends cls {
200200
const targetPath = resolve(this.path, meta.resolved)
201201
const targetLoc = relpath(this.path, targetPath)
202202
const target = nodes.get(targetLoc)
203+
204+
if (!target) {
205+
const err = new Error(`Missing target in lock file: "${targetLoc}" is referenced by "${location}" but does not exist.\nThis is likely due to a damaged lock file. Remove the entry for "${location}" from your lock file and run npm install again.`)
206+
err.code = 'EMISSINGTARGET'
207+
throw err
208+
}
209+
203210
const link = this.#loadLink(location, targetLoc, target, meta)
204211
nodes.set(location, link)
205212
nodes.set(targetLoc, link.target)

workspaces/arborist/test/arborist/load-virtual.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,45 @@ t.test('do not bundle the entire universe', async t => {
245245
'yaml',
246246
].sort())
247247
})
248+
249+
t.test('error when link target is missing', async t => {
250+
const path = t.testdir({
251+
'package.json': JSON.stringify({
252+
name: 'root',
253+
workspaces: ['packages/*'],
254+
}),
255+
'package-lock.json': JSON.stringify({
256+
name: 'root',
257+
lockfileVersion: 3,
258+
packages: {
259+
'': {
260+
workspaces: ['packages/*'],
261+
},
262+
// This is the problematic entry - a link with no corresponding target
263+
'node_modules/@my-scope/my-package': {
264+
resolved: 'packages/some-folder/my-package',
265+
link: true,
266+
},
267+
// Missing entry for 'packages/some-folder/my-package'
268+
},
269+
}),
270+
packages: {
271+
'some-folder': {
272+
'my-package': {
273+
'package.json': JSON.stringify({
274+
name: '@my-scope/my-package',
275+
version: '1.0.0',
276+
}),
277+
},
278+
},
279+
},
280+
})
281+
282+
const arb = new Arborist({ path })
283+
284+
// The loadVirtual call should fail with EMISSINGTARGET error
285+
await t.rejects(arb.loadVirtual(), {
286+
code: 'EMISSINGTARGET',
287+
message: /Missing target in lock file.*but does not exist/,
288+
})
289+
})

0 commit comments

Comments
 (0)