Skip to content

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

@ljharb

Description

@ljharb

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions