Running Node Electron app gives ENOENT error in NixOS

I’m wondering if this ENOENT errors is the same file not found error as when running non-nix binaries that can not find lib files or similar.

This is how I normally run my electron app:

$ npm install
...
$ npm run build
...
$ ./node_modules/.bin/electron ./dist/main/entry.js 
events.js:187
      throw er; // Unhandled 'error' event
      ^

Error: spawn /home/trusktr/src/velodyne_sw+mapper-replay/node_modules/electron/dist/electron ENOENT
    at Process.ChildProcess._handle.onexit (internal/child_process.js:264:19)
    at onErrorNT (internal/child_process.js:456:16)
...

Looks like the same issues:

As a newb to NixOS, as much as I love the concept, it seems like a pain when it comes to working on project like mine, that depend on native binaries installed in the project with npm install.

The binary in particular is at ./node_modules/electron/dist/electron, and starts with

^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^C^@>^@^A^@^@^@^@àÜ^

I have a bunch of projects cloned locally that I want to work on now that I’ve moved to NixOS. Each one of them may use a different version of electron that was locally installed with npm install.

I wonder how to work with projects like these, without changing the workflows in Traditional Linux or macOS, yet still be able to work on them in NixOS.

Even if I were to put electron in my PATH, built with nix, the npm commands place ./node_modules/.bin at the beginning of PATH so the commands will still use the electron that is locally installed and not patched.

Hmmmm :thinking:, maybe in the NixOS cases, I simply need to delete the locally-installed electron, then build the one I want and enter nix-shell, so that it is in PATH and not overridden by the local one. I wonder if node2nix takes care of most of this.

Or maybe I need to make tooling that patches the local binaries just in the NixOS case, calling patchelf myself?

1 Like

Ok, I think I’m starting to get somewhere.

I ran

patchelf --set-interpreter "$(cat $(echo $(nix-build --no-out-link -E 'with import <nixpkgs> {}; pkgs.stdenv.cc')/nix-support/dynamic-linker))" ./node_modules/electron/dist/electron

and now I get this error:

$ ./node_modules/.bin/electron ./dist/main/entry.js
/home/trusktr/project/node_modules/electron/dist/electron: error while loading shared libraries: libgobject-2.0.so.0: cannot open shared object file: No such file or directory

Ahhh, I didn’t realize electron is already a package. Searching “electron” at NixOS Search did not show an electron package on the first page. Seems like package-name matches should be prioritized there.

So I tried it: I ran nix-shell -p electron and deleted ./node_modules/.bin/electron and yaaaay, it launched.

But I now I have a runtime error in the electron console:

Uncaught Error: libstdc++.so.6: cannot open shared object file: No such file or directory
    at process.module.(anonymous function) [as dlopen] (ELECTRON_ASAR.js:160:31)
    at Object.Module._extensions..node (internal/modules/cjs/loader.js:722)
    at Object.module.(anonymous function) [as .node] (ELECTRON_ASAR.js:160:31)
...

Looks like I need to point LD_LIBRARY_PATH to a certain nix store? Is there a command that I can run to specify the package that provides libstdc++ and that will update LD_LIBRARY_PATH in a nix-shell?

EDIT:

Aaaaah, got it to work like this:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/nix/store/784rh7jrfhagbkydjfrv
68h9x3g4gqmk-gcc-8.3.0-lib/lib/ \
  electron ./dist/main/entry.js

while inside nix-shell with the electron package in scope.

Now I wonder how we can make this simpler. Maybe I can put this in a shell.nix at the root of the project? I have a newbie gut feeling that manually setting LD_LIBRARY_PATH is not the best way to do this.

3 Likes

you can use LD_LIBRARY_PATH, you can generate node_modules using yarn2nix (or GitHub - adnelson/nixfromnpm: Convert NPM packages into nix expressions is very good though I didnt try it) and override electron package, you can use lorri

2 Likes

@srghma Thanks for pointing those out! Lorri looks neat, I’ll try that one first, and then see about committing a .nix file in each of my repos.

But even if I have the proper electron in PATH (thanks to lorri or nix-shell or whatever), I wonder how to prevent npm from overriding electron. The npm command prepends ./node_modules/.bin/ to the PATH in its subshell, so it forces npm commands (f.e. npm start) to use the non-patched electron from node_modules.

Any ideas?

use yarn2nix to generate node_modules and override electron there (I dont know how, maybe pr is needed, check for examples in github), it’s universal approach, even if LD_LIBRARY_PATH doesnt help (e.g. when path to libraries is hardcoded in machine code)

i also found this way to do it.

there is a env var to set the electron binary Environment Variables | Electron

so its as simple as doing a nix shell like that

with import <nixpkgs> {};


mkShell {
    nativeBuildInputs = [
        nodejs-15_x
        yarn
        electron_11
    ];

    ELECTRON_OVERRIDE_DIST_PATH = "${electron_11}/bin/electron";
}
3 Likes

Edit:
ELECTRON_OVERRIDE_DIST_PATH = "${electron_11}/bin/electron";
Shoud be
ELECTRON_OVERRIDE_DIST_PATH = "${electron_11}/bin/";

1 Like

One possibility is to use pkgs.buildFHSUserEnv in your shell.nix

Thank you very much!
The yarn-electron-nodejs stuff under nix should be documented somewhere.