Wrong module versions used in packaged app, causing it to fail to load
- Electron-Builder Version:
25.0.5 - Node Version:
22.8.0 - npm Version:
10.8.0 - Electron Version:
32.1.0 - Electron Type (current, beta, nightly):
current - Target:
macOS arm64
There's an issue with the latest electron-builder where after packaging an app, the node_modules directory will include wrong module versions for sub-modules.
I'll explain better with a reproducible example:
- Run this command:
npm create --yes [email protected] -- --template electron-typescript-react --name electron-builder-issueThis scaffolds a
node-llama-cppElectron project that allows you to run LLMs locally on your machine - Select any model from the list, it doesn't matter which one for this issue reproduction
cd electron-builder-issue- Open
package.jsonand remove thepostinstallscript to skip the model download npm installnpm run build- Launch the app you built (under the
release/mac-arm64directory) and see that it works - Close the app
- Open
package.json. UnderdevDependencies, change theelectron-builderversion to25.0.5 npm installnpm run build- Launch the app and see that it fails to open with some error.
Sometimes it's about
require() of ES Module, sometimes it's about a missing import, it's pretty random from my testings. Locate from the long error which module is "the importer" (the one trying to import another module), and which module is "the imported" (the module that was attempted to be imported).
This is the error I received when trying to open the app:
Uncaught Exception:
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/user/Documents/workspace/electron-builder-issue/release/mac-arm64/node-llama-cpp-electron-example.app/Contents/Resources/app.asar/node_modules/ansi-regex/index.js from /Users/user/Documents/workspace/electron-builder-issue/release/mac-arm64/node-llama-cpp-electron-example.app/Contents/Resources/app.asar/node_modules/string-width/node_modules/strip-ansi/index.js not supported.
Instead change the require of /Users/user/Documents/workspace/electron-builder-issue/release/mac-arm64/node-llama-cpp-electron-example.app/Contents/Resources/app.asar/node_modules/ansi-regex/index.js in /Users/user/Documents/workspace/electron-builder-issue/release/mac-arm64/node-llama-cpp-electron-example.app/Contents/Resources/app.asar/node_modules/string-width/node_modules/strip-ansi/index.js to a dynamic import() which is available in all CommonJS modules.
at c._load (node:electron/js2c/node_init:2:17025)
at Object.<anonymous> (/Users/user/Documents/workspace/electron-builder-issue/release/mac-arm64/node-llama-cpp-electron-example.app/Contents/Resources/app.asar/node_modules/string-width/node_modules/strip-ansi/index.js:2:19)
In my error:
"The importer" is: string-width/node_modules/strip-ansi
"The imported" is: ansi-regex
The above error happened because some of the code was trying to load some version of a module but instead received a completely different version of it.
Here's how you can validate that this is indeed the issue:
cd release/mac-arm64/node-llama-cpp-electron-example.app/Contents/Resources/npx asar e app.asar app.contentcat ./app.content/node_modules/ansi-regex/package.jsonand see that the version of the bundledansi-regexis6.1.0cat ./app.content/node_modules/string-width/node_modules/strip-ansi/package.jsonand see this in thepackage.jsonofstrip-ansi:"dependencies": { "ansi-regex": "^5.0.1" }
As you can see, strip-ansi expected a ^5.0.1 version of ansi-regex, but actually received 6.1.0, which is incompatible.
From my testings, this issue doesn't happen with electron-builder version 25.0.0, but does happen with 25.0.1.
Because of this issue, I downgraded the version of electron-builder in the node-llama-cpp Electron template for now until this is resolved.
Can you try to repro on next 25.1.4? There were some updates from an upstream dependency that were merged in.
I forgot to mention it but I already tried, and the issue is still there.
Looking at the linked issue, you mentioned that it doesn't occur in 25.0.0, but does in 25.0.1. This may be the offending PR then since it's related to the module dependency tree resolution changes in upstream dependency app-builder-bin https://github.com/electron-userland/electron-builder/pull/8353/files
@beyondkmp can you take a look at this when you have a chance since it looks to be related to app-builder?
I have also those issues. Tried also to use 25.1.4 but starting from 25.x my app isn't working anymore after electron build process.
We get the same issue after upgrading to 25.x from 24.x in our CI pipeline. Weirdly only on macOS/Linux builds so far, and mostly different dependencies, varies from build to build.
@giladgd I have confirmed that this MR(https://github.com/develar/app-builder/pull/138) can fix this issue.
i had a somewhat similar issue here i think ...has similar 'wrong version of dependency' used/installed in deep node_modules folder with multiple versions of things.... https://github.com/electron-userland/electron-builder/issues/8503
my question is how is the node_modules folder being constructed, is it much different than before and why the change?
the "varies from build to build" is quite strange also!
@giladgd deploying release v25.1.6 now. Please update when you have a chance
I'm having a similar issue with Electron 24.13.3 on a yarn berry mono repo with hoisted dependencies:
Root folder:
node_modules[email protected](hoisted)[email protected](hoisted)
packages/myprojectnode_modules[email protected](non hoisted, subdependency of other dependency)
myproject depends on [email protected] and [email protected] depends on is-stream@^2.0.0
When standing inside packages/myproject and calling require('winston') using Node.js, [email protected] will be resolved and used (as expected), however when built using electron-builder, [email protected] will be bundled and it breaks because [email protected] is an ESM module (and winston doesn't really support that version as specified in its package.json file).
I think this is the same issue as #4516 (electron v21) and so I don't think it's a regression introduced in v25. see example here: https://github.com/kittaakos/test-electron-builder
I think electron-builder does not currently work correctly (and has never worked) with mono repostories with hoisted dependencies: It does not respect semver for subdependencies. It looks like some of this code has to be rewritted to properly resolve such dependencies: NodeModuleCopyHelper.ts or appFileCopier.
I'm not sure what's the best workaround, but probably what works is to completely ditch asar (except for packages where it's absolutely needed) and instead use a different bundler like esbuild, electron-vite etc to bundle all the main/preload process JS into a single JS file.
I'm having a similar issue with Electron 24.13.3 on a yarn berry mono repo with hoisted dependencies:
Root folder:
node_modules
[email protected](hoisted)[email protected](hoisted)
packages/myproject
node_modules
[email protected](non hoisted, subdependency of other dependency)
myprojectdepends on[email protected]and[email protected]depends onis-stream@^2.0.0When standing inside
packages/myprojectand callingrequire('winston')using Node.js,[email protected]will be resolved and used (as expected), however when built using electron-builder,[email protected]will be bundled and it breaks because[email protected]is an ESM module (and winston doesn't really support that version as specified in its package.json file).I think this is the same issue as #4516 (electron v21) and so I don't think it's a regression introduced in v25. see example here: https://github.com/kittaakos/test-electron-builder
I think electron-builder does not currently work correctly (and has never worked) with mono repostories with hoisted dependencies: It does not respect semver for subdependencies. It looks like some of this code has to be rewritted to properly resolve such dependencies: NodeModuleCopyHelper.ts or appFileCopier.
I'm not sure what's the best workaround, but probably what works is to completely ditch asar (except for packages where it's absolutely needed) and instead use a different bundler like esbuild,
electron-viteetc to bundle all the main/preload process JS into a single JS file.
@mifi I have tested electron-builder v25.1.8 and it has resolved the issue in #4516 (electron v21). Could you please test if v25.1.8 has resolved your issue as well?
@beyondkmp Sorry for the late response.
I've just tested version 25.1.8 and it seems to fix this issue.
Version 26.0.0-alpha.3 also works well.
Thanks for fixing this issue!
@beyondkmp 25.1.8 fixes the issue, thanks alot!