sharp icon indicating copy to clipboard operation
sharp copied to clipboard

Electron on Windows: The specified module could not be found

Open ivancuric opened this issue 4 years ago • 10 comments

Reproduction repo: https://github.com/ivancuric/native-repro-sharp

In this repo I am using 3 different native modules: an included one built with cmake (video-module), a dummy native module (native-hello-world), and sharp. I am running this on Windows 10.

Sharp is the only module that throws an error after the initial installation and build on yarn start, even though the module is present at the location:

D:\dev\native-repro-sharp\node_modules\sharp\lib\constructor.js:32 Uncaught Error: 
Something went wrong installing the "sharp" module

The specified module could not be found.
\\?\D:\dev\native-repro-sharp\node_modules\sharp\build\Release\sharp.node

- Remove the "node_modules/sharp" directory then run
  "npm install --ignore-scripts=false --verbose sharp" and look for errors
- Consult the installation documentation at https://sharp.pixelplumbing.com/install
- Search for this error at https://github.com/lovell/sharp/issues

    at Object.<anonymous> (D:\dev\native-repro-sharp\node_modules\sharp\lib\constructor.js:32)
    at Object.<anonymous> (D:\dev\native-repro-sharp\node_modules\sharp\lib\constructor.js:394)
    at Module._compile (internal/modules/cjs/loader.js:1078)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1108)
    at Module.load (internal/modules/cjs/loader.js:935)
    at Module._load (internal/modules/cjs/loader.js:776)
    at Function.f._load (electron/js2c/asar_bundle.js:5)
    at Function.o._load (electron/js2c/renderer_init.js:33)
    at Module.require (internal/modules/cjs/loader.js:959)
    at require (internal/modules/cjs/helpers.js:88)

Removing node_modules/sharp doesn't help. What does help is running yarn install --force an additional time.

You can see the difference in the node_modules/sharp directory between the initial and second installation here: https://editor.mergely.com/3aNte8dC/

What could be causing this? Seems that the install script in sharp's package.json isn't being run properly because running it manually afterwards from the node_modules directory works fine.

On the branch forge-hook-hack, I am running node node_modules/sharp/install/dll-copy after every rebuild:

$ node node_modules/sharp/install/dll-copy
sharp: Creating D:\dev\native-repro-sharp\node_modules\sharp\build\Release
sharp: Copying DLLs from D:\dev\native-repro-sharp\node_modules\sharp\vendor\8.10.6\lib to D:\dev\native-repro-sharp\node_modules\sharp\build\Release

ivancuric avatar Jun 23 '21 11:06 ivancuric

Hi, does this still happen if you remove the native-addons/video-module dependency? If so, please can you remove that from native-repro-sharp to make it more minimal and therefore easier for someone else to try to reproduce.

lovell avatar Jun 26 '21 07:06 lovell

It does, and I removed the module. The issue is (somewhat) resolved in the https://github.com/ivancuric/native-repro-sharp/tree/forge-hook-hack branch.

What I needed to do is run node node_modules/sharp/install/dll-copy after the initial rebuild that happens on the first run.

This is done before each app run in the forge config:

    generateAssets: async () => {
      return new Promise((resolve, reject) => {
        const npmInstall = spawn('yarn', ['fix-sharp'], {
          stdio: 'inherit',
          shell: true,
        });
        npmInstall.on('close', (code) => {
          if (code === 0) {
            resolve();
          } else {
            reject(new Error('process finished with error code ' + code));
          }
        });
        npmInstall.on('error', (error) => {
          reject(error);
        });
      });
    },

ivancuric avatar Jun 26 '21 12:06 ivancuric

Thanks, it looks like you're affected by https://github.com/electron/electron-rebuild/issues/520

sharp provides prebuilt binaries based on Node-API (N-API) that are designed to "just work" with all supported versions of Node.js and Electron, but electron-rebuild is erroneously ignoring these.

lovell avatar Jun 26 '21 18:06 lovell

Thanks for the input, gonna see if I can forward this issue!

ivancuric avatar Jun 26 '21 20:06 ivancuric

I've heard from other sharp+Electron users (there are many) that electron-builder provides better support for Node-API based modules than electron-forge, so that might be worth investigating too.

lovell avatar Jun 29 '21 08:06 lovell

Thanks, I'll check it out.

On Tue, Jun 29, 2021, 10:36 Lovell Fuller @.***> wrote:

I've heard from other sharp+Electron users (there are many) that electron-builder provides better support for Node-API based modules than electron-forge, so that might be worth investigating too.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/lovell/sharp/issues/2764#issuecomment-870395983, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAVSGJ56LLPFYAERWD6HSRDTVGAXDANCNFSM47FSYDUA .

ivancuric avatar Jun 29 '21 08:06 ivancuric

@lovell i'm having the same problem with electron-builder with asar enabled.

hiukky avatar Jun 29 '21 23:06 hiukky

I've been looking into this more and I'm working on a fix for the above mentioned issue with electron-rebuild where it fails to pass the correct parameters to prebuild-install.

However, if loading a prebuilt binary fails, electron-rebuild falls back to building from source. In my testing, it does in fact do this and it completes successfully. It looks like there is something wrong with the binary output which stops it from being loaded at runtime.

@ivancuric reports this which appears to suggest he has a similar result:

even though the module is present at the location

Is sharp expected to work when building from source, or does it only work from prebuilt binaries?

I've tried ref-napi and some other Node-API modules and electron-rebuild successfully builds them from source and they load correctly.

timfish avatar Jun 30 '21 20:06 timfish

@timfish Thank you for working on a fix for this. sharp can be built from source and should work, but for Windows note the DLL-copying command that runs as part of npm install:

https://github.com/lovell/sharp/blob/7467fa8b50d280780dfa9fe9a7248deaa499c7a1/package.json#L83

I took a quick look at your PR. Perhaps running electron-rebuild should be a "no-op" when using Node-API as the existing file(s) already in place will work?

lovell avatar Jun 30 '21 20:06 lovell

electron-rebuild is often used to compile binaries for different architectures to the current one so you can't rely on the existing binaries being good. For example most devs will be using x64 node but many Electron apps are packaged for ia32 on Windows so they run on both platforms.

There is also the issue that there's no easy way to detect if a module uses Node-API. There's binary.napi_versions in package.json but that is only there for modules that use prebuild tools. ref-napi for example doesn't have anything obvious to denote that it's Node-API.

Whereas the node ecosystem relies on install scripts to copy binaries with the platform and arch swapped via environment variables, electron-rebuild instead relies on directly calling node-gyp, prebuild-install, etc. This means that it's currently not possible to release a native module built with anything other than gyp. It's a bit of a mess 🤷‍♂️

timfish avatar Jun 30 '21 20:06 timfish

The use of prebuild-install will be going away with https://github.com/lovell/sharp/issues/3750 - please subscribe to it for updates. (I'm unsure how this will impact the various Electron packagers specifically but the proposed approach is designed to be more package manager friendly overall.)

lovell avatar Sep 26 '23 21:09 lovell

The specified module could not be found.

The reason for this error may be the .node file cannot find its required .dll files.

LZQCN avatar Nov 14 '23 18:11 LZQCN

v0.33.0 is now available and no longer depends on prebuild-install - everything is controlled via your choice of package manager.

lovell avatar Nov 29 '23 13:11 lovell