cli icon indicating copy to clipboard operation
cli copied to clipboard

[BUG] Directly requested packages incorrectly marked as peer and not installed with --omit-peer

Open blexrob opened this issue 2 months ago • 1 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues

This issue exists in the latest npm version

  • [x] I am using the latest npm

Current Behavior

When installing a package and another package that has the first package as peer dependency, the first package is marked as peer dependency, and not installed when --omit=peer is added to the installation command.

Example: installing ajv and ajv-draft-04. ajv-draft-04 has ajv as peer dependency. When using --omit=peer, ajv won't be installed.

$ npm install --omit=peer ajv ajv-draft-04

added 5 packages in 1s
$ npm list
npm-test@ /private/tmp/npm-test
├── [email protected]
├── UNMET DEPENDENCY ajv@^8.17.1
├── [email protected] extraneous
├── [email protected] extraneous
├── [email protected] extraneous
└── [email protected] extraneous

npm error code ELSPROBLEMS
npm error missing: ajv@^8.17.1, required by npm-test@
npm error extraneous: [email protected] /private/tmp/npm-test/node_modules/fast-deep-equal
npm error extraneous: [email protected] /private/tmp/npm-test/node_modules/fast-uri
npm error extraneous: [email protected] /private/tmp/npm-test/node_modules/json-schema-traverse
npm error extraneous: [email protected] /private/tmp/npm-test/node_modules/require-from-string

In this case, ajv is incorrectly marked as peer dependency. The package-lock.json has a "peer": true for "node_modules/ajc".

package-lock.json:

{
  "name": "npm-test",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "dependencies": {
        "ajv": "^8.17.1",
        "ajv-draft-04": "^1.0.0"
      }
    },
    "node_modules/ajv": {
      "version": "8.17.1",
      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
      "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
      "license": "MIT",
      "peer": true,
      "dependencies": {
        "fast-deep-equal": "^3.1.3",
        "fast-uri": "^3.0.1",
        "json-schema-traverse": "^1.0.0",
        "require-from-string": "^2.0.2"
      },
      "funding": {
        "type": "github",
        "url": "https://github.com/sponsors/epoberezkin"
      }
    },
    "node_modules/ajv-draft-04": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz",
      "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==",
      "license": "MIT",
      "peerDependencies": {
        "ajv": "^8.5.0"
      },
      "peerDependenciesMeta": {
        "ajv": {
          "optional": true
        }
      }
    },
    "node_modules/fast-deep-equal": {
      "version": "3.1.3",
      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
      "license": "MIT"
    },
    "node_modules/fast-uri": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
      "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/fastify"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/fastify"
        }
      ],
      "license": "BSD-3-Clause"
    },
    "node_modules/json-schema-traverse": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
      "license": "MIT"
    },
    "node_modules/require-from-string": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    }
  }
}

Expected Behavior

I'd expect that packages that are requested directly in the package.json (and recursively through normal dependencies) are all installed when --omit=peer, even when they are peer dependency by one or more of the installed packages.

Thus, npm install --omit=peer ajv ajv-draft-04 should install ajv.

Steps To Reproduce

  1. In this environment... MacOS, Linux
  2. With this config... Node 24.10.0, npm 11.6.1 and 11.6.2 npm 11.6.0 doesn't have this problem.
  3. Run:
npm install --omit=peer ajv ajv-draft-04
npm list
  1. See error
npm-test@ /private/tmp/npm-test
├── [email protected]
├── UNMET DEPENDENCY ajv@^8.17.1
├── [email protected] extraneous
├── [email protected] extraneous
├── [email protected] extraneous
└── [email protected] extraneous

npm error code ELSPROBLEMS
npm error missing: ajv@^8.17.1, required by npm-test@
npm error extraneous: [email protected] /private/tmp/npm-test/node_modules/fast-deep-equal
npm error extraneous: [email protected] /private/tmp/npm-test/node_modules/fast-uri
npm error extraneous: [email protected] /private/tmp/npm-test/node_modules/json-schema-traverse
npm error extraneous: [email protected] /private/tmp/npm-test/node_modules/require-from-string

Environment

  • npm: 11.6.2
  • Node.js: v24.10.0
  • OS Name: 15.6.1 (24G90)
  • System Model Name: Macbook Pro
  • npm config:
; "builtin" config from /usr/local/lib/node_modules/npm/npmrc

prefix = "/usr/local"

; "user" config from /Users/rob/.npmrc

//registry.npmjs.org/:_authToken = (protected)

; node bin location = /usr/local/Cellar/node/24.10.0/bin/node
; node version = v24.10.0
; npm local prefix = /Users/rob
; npm version = 11.6.2
; cwd = /Users/rob
; HOME = /Users/rob
; Run `npm config ls -l` to show all defaults.

blexrob avatar Oct 10 '25 08:10 blexrob

Fixed by #8645

Below command is run from a mytest folder inside the npm project on the fix branch. node ../ is equivalent to npm.

~/Projects/npm-cli/mytest on reproducible-install
$ node ../ install --omit=peer ajv ajv-draft-04
npm list

added 6 packages, and audited 7 packages in 2s

2 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
[email protected] /Users/liam.mitchell/Projects/npm-cli/mytest
├── [email protected]
└── [email protected]

~/Projects/npm-cli/mytest on reproducible-install
$ node ../ list
[email protected] /Users/liam.mitchell/Projects/npm-cli/mytest
├── [email protected]
└── [email protected]

liamcmitchell avatar Oct 12 '25 19:10 liamcmitchell