Skip to content

fix(arborist): skip lockfile entries for optional deps with incomplete manifests#9362

Merged
owlstronaut merged 1 commit into
release/v11from
backport/v11/9343
May 15, 2026
Merged

fix(arborist): skip lockfile entries for optional deps with incomplete manifests#9362
owlstronaut merged 1 commit into
release/v11from
backport/v11/9343

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Backport of #9343 to release/v11.

…e manifests (#9343)

### What

When using a proxy/upstream registry (e.g. Azure Artifacts), npm 11
writes lockfile entries for platform-specific optional dependencies
without `version`, `resolved`, or `integrity` fields. Subsequent `npm
ci` fails with `Invalid Version:` errors.

Example broken lockfile entry:
```json
"node_modules/@esbuild/aix-ppc64": {
  "optional": true
}
```

### Why

`#fetchManifest()` in `build-ideal-tree.js` fetches manifests for ALL
platform variants of optional dependencies. Proxy registries that
haven't cached packages for non-current platforms return incomplete
metadata (missing `version` field). npm creates a Node with empty
`pkg.version`, and `metaFromNode()` writes `{"optional": true}` to the
lockfile without version.

npm 10 never attempted to resolve non-current-platform variants, so this
only affects npm 11+.

### How

Two-layer defense:

1. **`build-ideal-tree.js` (`#nodeFromSpec`)**: When a registry manifest
lacks a `version` field, treat it as an `EINCOMPLETEMANIFEST` load
failure so that `#pruneFailedOptional()` marks it inert. Only applies to
`spec.registry` specs (not `file:` dependencies which may legitimately
omit version).

2. **`shrinkwrap.js` (`commit()`)**: Skip writing entries where the node
is optional, has no version, and is not the root. This acts as a
defense-in-depth layer.

### Testing

- Unit test added to `workspaces/arborist/test/shrinkwrap.js` —
simulates proxy registry scenario where an optional dep node has no
version
- All existing tests pass (`shrinkwrap.js` 45/45, `build-ideal-tree.js`
114/114)
- Manually verified with Azure Artifacts upstream proxy feed:
- Before fix: 46 broken lockfile entries (optional deps without version)
  - After fix: 0 broken entries
  - Output matches npm 10 behavior

Closes #9342

---------

Co-authored-by: Michael Smith <owlstronaut@github.com>
(cherry picked from commit 822ce86)
@owlstronaut owlstronaut merged commit d7e195a into release/v11 May 15, 2026
17 checks passed
@owlstronaut owlstronaut deleted the backport/v11/9343 branch May 15, 2026 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants