Arborist crashes with "Cannot read properties of null (reading 'matches')" on a Link with a null target

Open Beginner friendly
#9,459 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
74/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
javascript, nodejs
Domain
cli, tooling

Research direction

Start at Link.matches in lib/node.js:1183 and reproduce the failure by running npm install after vlt install or bun install in a workspace monorepo. Trace the callers shown in lib/node.js, lib/place-dep.js, and lib/arborist/build-ideal-tree.js, then verify that a missing link target no longer causes an unhandled TypeError and produces a clean, actionable error.

Written by the indexing model from the issue text.

Description

Summary

Link.matches (@npmcli/arborist/lib/node.js:1183) dereferences this.target without a null check:

if (this.isLink) {
  return node.isLink && this.target.matches(node.target)
}

When node_modules contains store-style symlinks whose targets npm hasn't loaded as nodes - e.g. a tree populated by bun (node_modules/.bun/...) or vlt (node_modules/.vlt/...), neither of which writes node_modules/.package-lock.json - this.target is null, so any npm install crashes mid-reify with an unhandled TypeError instead of a clean, actionable error.

Steps to reproduce
  1. In any npm workspace monorepo, install deps with another package manager: vlt install (or bun install).
  2. Run npm install.
Actual
TypeError: Cannot read properties of null (reading 'matches')
    at Link.matches (@npmcli/arborist/lib/node.js:1183:41)
    at Link.canDedupe (lib/node.js:1127:15)
    at PlaceDep.pruneDedupable (lib/place-dep.js:426:14)
    at new PlaceDep (lib/place-dep.js:278:14)
    at #buildDepStep (lib/arborist/build-ideal-tree.js:933:18)
    at async Arborist.buildIdealTree (lib/arborist/build-ideal-tree.js:170:7)
    at async Arborist.reify (lib/arborist/reify.js:111:5)
    at async Install.exec (lib/commands/install.js:146:5)
Expected

A clean error (e.g. "node_modules was not installed by npm"), not an unhandled TypeError. Minimal fix: guard the link branch, e.g. return node.isLink && !!this.target && this.target.matches(node.target).

Alternatively, regenerate the hidden lockfile whenever it's absent.

Environment

npm 11.13.0, Node 26 (also reproduced on Node 22/24 in CI).

Dominant language
JavaScript
Stars
10.1k
Forks
4.7k
Avg merge
2d 2h
Merged PRs (30d)
21

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from npm/cli

All issues in npm/cli

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.