Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Platform-specific optional dependencies not being included in package-lock.json when reinstalling with node_modules present #4828

Open
2 tasks done
JustinChristensen opened this issue Apr 29, 2022 · 124 comments
Labels
Bug thing that needs fixing Needs Triage needs review for next steps Release 8.x work is associated with a specific npm 8 release

Comments

@JustinChristensen
Copy link

JustinChristensen commented Apr 29, 2022

Is there an existing issue for this?

  • I have searched the existing issues

This issue exists in the latest npm version

  • I am using the latest npm

Current Behavior

[user@host:foo] $ npm -v
8.8.0
[user@host:foo] $ node
Welcome to Node.js v16.14.2.
Type ".help" for more information.
> process.arch
'arm64'

I'm working on a team that utilizes a mix of x64-based and m1-based macs, and has CI build processes that uses musl. We're seeing that npm is skipping platform-specific optional dependencies for packages such as @swc/core as a result of the package-lock.json file being generated without all of them included. In our case, this then causes linting to throw an exception, because one of our eslint plugins depends on @swc, which depends on having the platform specific @swc package also installed.

There seems to be at least two stages of cause to this. Firstly, when installing @swc/core from a clean slate working directory npm generates a package-lock.json with all of the optional dependencies for @swc/core listed:

[user@host:foo] $ npm install @swc/core
[user@host:foo] $ grep 'node_modules/@swc/core-*' package-lock.json
    "node_modules/@swc/core": {
    "node_modules/@swc/core-android-arm-eabi": {
    "node_modules/@swc/core-android-arm64": {
    "node_modules/@swc/core-darwin-arm64": {
    "node_modules/@swc/core-darwin-x64": {
    "node_modules/@swc/core-freebsd-x64": {
    "node_modules/@swc/core-linux-arm-gnueabihf": {
    "node_modules/@swc/core-linux-arm64-gnu": {
    "node_modules/@swc/core-linux-arm64-musl": {
    "node_modules/@swc/core-linux-x64-gnu": {
    "node_modules/@swc/core-linux-x64-musl": {
    "node_modules/@swc/core-win32-arm64-msvc": {
    "node_modules/@swc/core-win32-ia32-msvc": {
    "node_modules/@swc/core-win32-x64-msvc": {

And it only installs the platform specific package:

[user@host:foo] $ ls -l node_modules/@swc/
total 0
drwxr-xr-x  22 user  staff  704 Apr 29 15:39 core
drwxr-xr-x   6 user  staff  192 Apr 29 15:39 core-darwin-arm64

If I then remove my package-lock.json, leave my node_modules directory as-is, and then reinstall, I get:

[user@host:foo] $ rm -rf package-lock.json
[user@host:foo] $ npm install
[user@host:foo] $ grep 'node_modules/@swc/core-*' package-lock.json
    "node_modules/@swc/core": {
    "node_modules/@swc/core-darwin-arm64": {

That is, it then generates a package-lock.json with only the platform-specific dependency that was installed on this machine, and not with the other optional dependencies that should also be listed.

If you delete both node_modules AND package-lock.json, and then re-run npm install, it generates the correct lockfile with all of those optional dependencies listed.

The problem is that then, If the package-lock.json with the missing optional platform-specific dependencies gets checked into git and an x64 user pulls it down, or vice-versa, npm fails to detect that your platform's optional dependencies are missing in the lockfile and just silently skips installing the platform-specific dependency. For example, when I've got a package-lock.json that only contains the x64 @swc package because of the above problem (generated by my coworker on his x64 machine):

[user@host:foo] $ node
Welcome to Node.js v16.14.2.
Type ".help" for more information.
> process.arch
'arm64'
>
[user@host:foo] $ grep 'node_modules/@swc/core-*' package-lock.json
    "node_modules/@swc/core": {
    "node_modules/@swc/core-darwin-x64": {
[user@host:foo] $ ls
package-lock.json package.json

And I then install:

[user@host:foo] $ npm install
added 1 package in 341ms

1 package is looking for funding
  run `npm fund` for details
[user@host:foo] $ ls node_modules/@swc/
core

You can see that it fails to install the arm64 dependency or warn me in any way that the package-lock.json is missing my platform's dependency.

So yeah, two problems:

  1. npm is generating an inconsistent package-lock.json when node_modules has your platform-specific dependency installed.
  2. When installing from this inconsistent package-lock.json, npm fails to try to correct the problem by comparing the optional dependencies to what's listed upstream

Expected Behavior

  1. npm should preserve the full set of platform-specific optional deps for a package like @swc when rebuilding package-lock.json from an existing node_modules tree
  2. npm install should warn if the package-lock.json becomes inconsistent because of the first case

Steps To Reproduce

See above.

Environment

  • npm: 8.8.0
  • Node.js:
  • OS Name: OSX
  • System Model Name: Macbook Pro
[user@host:foo] $ npm -v
8.8.0
[user@host:foo] $ node -v
v16.14.2
[user@host:foo] $ uname -a
Darwin host.foo.com. 21.3.0 Darwin Kernel Version 21.3.0: Wed Jan  5 21:37:58 PST 2022; root:xnu-8019.80.24~20/RELEASE_ARM64_T8101 arm64
[user@host] $ npm config ls
; "user" config from /Users/user/.npmrc
; node bin location = /Users/user/.nvm/versions/node/v16.14.2/bin/node
; node version = v16.14.2
; npm local prefix = /Users/user/Development/foo
; npm version = 8.8.0
; cwd = /Users/user/Development/foo
; HOME = /Users/user
; Run `npm config ls -l` to show all defaults.
@JustinChristensen JustinChristensen added Bug thing that needs fixing Needs Triage needs review for next steps Release 8.x work is associated with a specific npm 8 release labels Apr 29, 2022
@JustinChristensen JustinChristensen changed the title [BUG] Platform-specific optional dependencies not being included in package-lock when reinstalling with node_modules/ present [BUG] Platform-specific optional dependencies not being included in package-lock when reinstalling with node_modules present Apr 29, 2022
@JustinChristensen JustinChristensen changed the title [BUG] Platform-specific optional dependencies not being included in package-lock when reinstalling with node_modules present [BUG] Platform-specific optional dependencies not being included in package-lock.json when reinstalling with node_modules present Apr 29, 2022
@JustinChristensen
Copy link
Author

@nlf

Sorry to ping you out of the blue, but this issue has been open for 11 days now without any movement. Is there anyone working on npm right now that might have the bandwidth to at least validate that this is indeed a problem as I've described it?

Just so that when someone does become available to do some development work they know that this is in the queue?

Please and thank you.

@JustinChristensen
Copy link
Author

Bump

@RobbieClarken
Copy link

I'm also encountering this issue with a Next.js project:

  • Deleting package-lock.json and running npm install on an M1 Mac results in a package-lock.json file that is no longer able to build the app on x86.
  • This can be fixed by deleting package-lock.json and node_modules and re-running npm install.

Unfortunately developers often don't realise the package-lock.json file is broken because everything continues to run fine on their machine. It is only when the build runs in CI that we learn it is broken.

Here is a reproduction:

$ node --version
v16.13.0
$ npm --version
8.12.1
$ npx create-next-app@latest
What is your project named? … my-app
Creating a new Next.js app in /Users/robbie/demo/my-app.
$ cd my-app/
$ npm install

up to date, audited 223 packages in 480ms

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

found 0 vulnerabilities
$ git status
On branch main
nothing to commit, working tree clean
$ rm package-lock.json
$ npm install

up to date, audited 223 packages in 579ms

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

found 0 vulnerabilities
$ # ************ package-lock.json is now incompatible with x86 ************
$ git diff
diff --git a/package-lock.json b/package-lock.json
index cbbf946..a87c1e5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -96,36 +96,6 @@
         "glob": "7.1.7"
       }
     },
-    "node_modules/@next/swc-android-arm-eabi": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.6.tgz",
-      "integrity": "sha512-BxBr3QAAAXWgk/K7EedvzxJr2dE014mghBSA9iOEAv0bMgF+MRq4PoASjuHi15M2zfowpcRG8XQhMFtxftCleQ==",
-      "cpu": [
-        "arm"
-      ],
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">= 10"
-      }
-    },
-    "node_modules/@next/swc-android-arm64": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.1.6.tgz",
-      "integrity": "sha512-EboEk3ROYY7U6WA2RrMt/cXXMokUTXXfnxe2+CU+DOahvbrO8QSWhlBl9I9ZbFzJx28AGB9Yo3oQHCvph/4Lew==",
-      "cpu": [
-        "arm64"
-      ],
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">= 10"
-      }
-    },
[...]
$ rm -r package-lock.json node_modules
$ npm install

added 222 packages, and audited 223 packages in 2s

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

found 0 vulnerabilities
$ # ************ package-lock.json is now ok again ************
$ git status
On branch main
nothing to commit, working tree clean

@pete55104
Copy link

I am also having this issue. I'm trying to run tests using jest with swc. The test runner is a linux image, but my dev machine is darwin. I can get it to work by either using --force to install the linux dependency, or I can install packages from inside the container... but github CI stands up the docker container in such a way that I can't easily install packages from in there, and that also prevents me from maintaining a cached node modules etc.

@johnculviner
Copy link

bump

@nikkhn
Copy link

nikkhn commented Jul 12, 2022

bump - cannot get optional dependencies (namely @swc/core-linux-arm64-gnu) to install on my linux distro

@sgoodluck
Copy link

bump

@alcuadrado
Copy link

Confirming that this issue is still present. It's particularly important for projects using NAPI modules, as tons of them use platform-specific packages.

jfsoul added a commit to guardian/prosemirror-typerighter that referenced this issue Sep 26, 2022
@AboldUSER
Copy link

Ran into this issue when creating a CI process for a repo where I use a Windows machine and the CI process is using Linux. My quick "fix" for now is to start the CI process by deleting the package-lock.json and running npm install instead of npm ci. I know this is not good practice, so looking forward to a real fix to come through.

@eliotSmithNYC
Copy link

bump

@douglassllc
Copy link

I am having a similar issue. My project uses @ffmpeg-installer/ffmpeg. While using npm v6 all optional dependencies (arch specific) are installed. After my upgrade to npm v8 the optional dependencies no longer install. Per the npm documentation I attempted using --include=optional, but this did not resolve the issue.

What has changed between v6 and v8 and is there an npm config option that will have v8 work similar to v6 when it comes to optional dependencies?

yoonsoohwa pushed a commit to yoonsoohwa/daedongmap_Frontend that referenced this issue Apr 23, 2024
Error: Cannot find module @rollup/rollup-darwin-arm64. npm has a bug related to optional dependencies (npm/cli#4828)
@ozknemoy
Copy link

to fix @nx (@rollup or others) optional deps inside package-lock.json, i downgraded npm to 6 version and removed lock.json. then npm install. then returned newer version of npm and again npm i. now i have perfect nx optional deps inside lock.json. and i do not have extra/unwanted optionalDependencies in package.json

@JamesCatt
Copy link

JamesCatt commented Apr 23, 2024

Ran into this issue with Vite + node 18.20.1/npm 10.5.0.

Clearing node_modules and package-lock.json then reinstalling with node 16.20.1/npm 8.19.4 worked correctly.

bylexus added a commit to bylexus/fparse that referenced this issue Apr 23, 2024
It seems that an npm issue causes build problems related to a divergence
in node_modules and package-lock.json:

npm/cli#4828

I hope this change will fix this.
@Austin-rgb
Copy link

Austin-rgb commented Apr 24, 2024

I'm also experiencing a problem related to when using angular/cli
$ng serve --open Node.js version v21.6.2 detected. Odd numbered Node.js versions will not enter LTS status and should not be used for production. For more information, please see https://nodejs.org/en/about/previous-releases/. An unhandled exception occurred: Cannot find module @rollup/rollup-android-arm64. npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). Please try npm i` again after removing both package-lock.json and node_modules directory.
See "/tmp/ng-qujNWE/angular-errors.log" for further details.
node:internal/process/promises:289
triggerUncaughtException(err, true /* fromPromise */);
^

Error: Cannot find module @rollup/rollup-android-arm64. npm has a bug related to optional dependencies (#4828). Please try npm i again after removing both package-lock.json and node_modules directory.
at requireWithFriendlyError (/home/ostiness/Desktop/project1/front/front/node_modules/rollup/dist/native.js:59:9)
at Object. (/home/ostiness/Desktop/project1/front/front/node_modules/rollup/dist/native.js:68:76)
... 2 lines matching cause stack trace ...
at Module.load (node:internal/modules/cjs/loader:1212:32)
at Module._load (node:internal/modules/cjs/loader:1028:12)
at cjsLoader (node:internal/modules/esm/translators:359:17)
at ModuleWrap. (node:internal/modules/esm/translators:308:7)
at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:323:24) {
[cause]: Error: dlopen failed: library "/home/ostiness/Desktop/project1/front/front/node_modules/@rollup/rollup-android-arm64/rollup.android-arm64.node" needed or dlopened by "/data/data/com.termux/files/usr/bin/node" is not accessible for the namespace "(default)"
at Module._extensions..node (node:internal/modules/cjs/loader:1475:18)
at Module.load (node:internal/modules/cjs/loader:1212:32)
at Module._load (node:internal/modules/cjs/loader:1028:12)
at Module.require (node:internal/modules/cjs/loader:1237:19)
at require (node:internal/modules/helpers:176:18)
at requireWithFriendlyError (/home/ostiness/Desktop/project1/front/front/node_modules/rollup/dist/native.js:41:10)
at Object. (/home/ostiness/Desktop/project1/front/front/node_modules/rollup/dist/native.js:68:76)
at Module._compile (node:internal/modules/cjs/loader:1378:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1437:10)
at Module.load (node:internal/modules/cjs/loader:1212:32) {
code: 'ERR_DLOPEN_FAILED'
}
}

Node.js v21.6.2`

Deleting package-lock.json and node_modules and then running npm i never fixed the problem

@kishor82
Copy link

Deleting the lock file and node_modules directory, and then running npm i, worked for me 🚀
Node.js v20.9.0

@mctrafik
Copy link

Deleting the lock file and node_modules directory, and then running npm i, worked for me 🚀 Node.js v20.9.0

Please stop posting this. It isn't a solution. For many of us regenerating the lockfile isn't an option because it causes a lot of packages to be upgraded to broken versions. And running this for one teammate with a certain architecture breaks it for other teammates with different architectures.

@localpcguy
Copy link

@mctrafik and others: If regenerating your node_modules leads to broken packages, then you have that problem to fix outside of the problem in this bug. You should always be able to start from scratch (i.e. delete node_modules and reinstall and have a working project). It may require better / more specific version specifications for example.

That doesn't mean it's a valid fix for this bug. And it is a very large pain to have to run regularly. So I don't advocate for it as a solution, but it is a sign of a broken project already if it isn't possible.

@kishor82
Copy link

@mctrafik Well, it's not the complete solution, but not all of us encounter issues with regenerating the lockfile.

@ljharb
Copy link
Collaborator

ljharb commented Apr 25, 2024

@localpcguy very well said.

#4828 (comment) is the correct answer - it's not a solution, but it should always be an available workaround, or else your dep graph is invalid. Fix that.

@hakaba
Copy link

hakaba commented Apr 26, 2024

@localpcguy in a CI and a industrialization process, this is not an option.

@schjetne
Copy link

I'm happy for the people with the luxury of just regenerating the lock file but if your build and deploy processes require a lock file and your architecture is incompatible with your deployment architecture you'll still have this problem.

Deleting the lock file is not recommended and it shouldn't be proposed as a "solution" to this problem for the 50th time in this discussion.

Adding some optional dependencies is not a real solution either as that will also fail in the scenario above.

There's an actual bug here and it's not being fixed. I have no idea why.

@D3press3dd
Copy link

I did this #4828 (comment) and it worked me

@chrisfosterelli
Copy link

Telling people here that they shouldn't fully rely on lockfiles to lock their package versions is sort of like critiquing someone whose engine is on fire because their lug nuts are not torqued correctly: Not technically wrong, but not really helping with the problem.

More seriously, we should be mindful about suggesting recreating it as a workaround because it's going to lead to different devs on different hardware constantly deleting / recreating the lock file as it thrashes around between platform versions, and it won't work in a lot of deployment scenarios. It pretty much defeats the purpose of the lockfile and creates a lot of busywork & large diffs, assuming it doesn't just break prod deploys. It might function for some in a pinch but they haven't actually worked around the problem, they've just hidden it by tieing the lockfile to their current platform...

I am also surprised this one has been here for almost two years with radio silence since it is a somewhat breaking bug.

@Azbesciak
Copy link

Since we have 2nd anniversary, is there any progress on that issue?

@isebbo
Copy link

isebbo commented May 7, 2024

Are there any progress to be seen?

@IRoye
Copy link

IRoye commented May 9, 2024

Are there any progress to be seen ? i just encountered this problem,the tip in the console
Please try npm i again after removing both package-lock.json and node_modules directory dosent work for me

@fshengw
Copy link

fshengw commented May 11, 2024

Is there an existing issue for this?

  • I have searched the existing issues

This issue exists in the latest npm version

  • I am using the latest npm

Current Behavior

[user@host:foo] $ npm -v
8.8.0
[user@host:foo] $ node
Welcome to Node.js v16.14.2.
Type ".help" for more information.
> process.arch
'arm64'

I'm working on a team that utilizes a mix of x64-based and m1-based macs, and has CI build processes that uses musl. We're seeing that npm is skipping platform-specific optional dependencies for packages such as @swc/core as a result of the package-lock.json file being generated without all of them included. In our case, this then causes linting to throw an exception, because one of our eslint plugins depends on @swc, which depends on having the platform specific @swc package also installed.

There seems to be at least two stages of cause to this. Firstly, when installing @swc/core from a clean slate working directory npm generates a package-lock.json with all of the optional dependencies for @swc/core listed:

[user@host:foo] $ npm install @swc/core
[user@host:foo] $ grep 'node_modules/@swc/core-*' package-lock.json
    "node_modules/@swc/core": {
    "node_modules/@swc/core-android-arm-eabi": {
    "node_modules/@swc/core-android-arm64": {
    "node_modules/@swc/core-darwin-arm64": {
    "node_modules/@swc/core-darwin-x64": {
    "node_modules/@swc/core-freebsd-x64": {
    "node_modules/@swc/core-linux-arm-gnueabihf": {
    "node_modules/@swc/core-linux-arm64-gnu": {
    "node_modules/@swc/core-linux-arm64-musl": {
    "node_modules/@swc/core-linux-x64-gnu": {
    "node_modules/@swc/core-linux-x64-musl": {
    "node_modules/@swc/core-win32-arm64-msvc": {
    "node_modules/@swc/core-win32-ia32-msvc": {
    "node_modules/@swc/core-win32-x64-msvc": {

And it only installs the platform specific package:

[user@host:foo] $ ls -l node_modules/@swc/
total 0
drwxr-xr-x  22 user  staff  704 Apr 29 15:39 core
drwxr-xr-x   6 user  staff  192 Apr 29 15:39 core-darwin-arm64

If I then remove my package-lock.json, leave my node_modules directory as-is, and then reinstall, I get:

[user@host:foo] $ rm -rf package-lock.json
[user@host:foo] $ npm install
[user@host:foo] $ grep 'node_modules/@swc/core-*' package-lock.json
    "node_modules/@swc/core": {
    "node_modules/@swc/core-darwin-arm64": {

That is, it then generates a package-lock.json with only the platform-specific dependency that was installed on this machine, and not with the other optional dependencies that should also be listed.

If you delete both node_modules AND package-lock.json, and then re-run npm install, it generates the correct lockfile with all of those optional dependencies listed.

The problem is that then, If the package-lock.json with the missing optional platform-specific dependencies gets checked into git and an x64 user pulls it down, or vice-versa, npm fails to detect that your platform's optional dependencies are missing in the lockfile and just silently skips installing the platform-specific dependency. For example, when I've got a package-lock.json that only contains the x64 @swc package because of the above problem (generated by my coworker on his x64 machine):

[user@host:foo] $ node
Welcome to Node.js v16.14.2.
Type ".help" for more information.
> process.arch
'arm64'
>
[user@host:foo] $ grep 'node_modules/@swc/core-*' package-lock.json
    "node_modules/@swc/core": {
    "node_modules/@swc/core-darwin-x64": {
[user@host:foo] $ ls
package-lock.json package.json

And I then install:

[user@host:foo] $ npm install
added 1 package in 341ms

1 package is looking for funding
  run `npm fund` for details
[user@host:foo] $ ls node_modules/@swc/
core

You can see that it fails to install the arm64 dependency or warn me in any way that the package-lock.json is missing my platform's dependency.

So yeah, two problems:

  1. npm is generating an inconsistent package-lock.json when node_modules has your platform-specific dependency installed.
  2. When installing from this inconsistent package-lock.json, npm fails to try to correct the problem by comparing the optional dependencies to what's listed upstream

Expected Behavior

  1. npm should preserve the full set of platform-specific optional deps for a package like @swc when rebuilding package-lock.json from an existing node_modules tree
  2. npm install should warn if the package-lock.json becomes inconsistent because of the first case

Steps To Reproduce

See above.

Environment

  • npm: 8.8.0
  • Node.js:
  • OS Name: OSX
  • System Model Name: Macbook Pro
[user@host:foo] $ npm -v
8.8.0
[user@host:foo] $ node -v
v16.14.2
[user@host:foo] $ uname -a
Darwin host.foo.com. 21.3.0 Darwin Kernel Version 21.3.0: Wed Jan  5 21:37:58 PST 2022; root:xnu-8019.80.24~20/RELEASE_ARM64_T8101 arm64
[user@host] $ npm config ls
; "user" config from /Users/user/.npmrc
; node bin location = /Users/user/.nvm/versions/node/v16.14.2/bin/node
; node version = v16.14.2
; npm local prefix = /Users/user/Development/foo
; npm version = 8.8.0
; cwd = /Users/user/Development/foo
; HOME = /Users/user
; Run `npm config ls -l` to show all defaults.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug thing that needs fixing Needs Triage needs review for next steps Release 8.x work is associated with a specific npm 8 release
Projects
None yet