Error: Cannot find module 'my-client'

I'm developing a node-contrib module that creates a few nodes for network communication. After writing it all up, I get an error message on node-red startup:

25 Mar 23:34:26 - [warn] [node-red-contrib-my-client/my-client] Error: Cannot find module 'my-client'

The first npm package I installed is 'node-red-contrib-my-client', following the instructions in the docs and a similar existing (and working) package. It requires 'my-client' as dependency which does the actual network protocol handling.

I've installed the contrib package with 'npm i C:\path\to\node-red-contrib-my-client' and it has created a link to my dev directory under node_modules. Looks good. That dev directory also has 'node_modules\my-client' in it. But I get the error message. Even when I install the dependency directly to node-red with 'npm i C:\path\to\my-client', it creates a second directory as a link, but it doesn't help.

What have I done wrong?

node-red 0.20.0 on Windows 10. The Node-RED GUI works and I see the nodes from the other package I installed. It has dependencies, too, as my package. But mine fails to load.

PS: Node-RED's debug and trace logging isn't helpful. It lists my contrib package among others but then shows the error message. I have no idea where this thing is looking for the files but it's the wrong place.

Update: The error message seems to come from this line in my contrib module:

module.exports = function (RED) {
    "use strict";
    var events = require("events");
    var MyClient = require("my-client");   // <----- ERROR

When I set that variable to null, the error goes away, but the code will not work without it. When I set the string to "../my-client", as specified in the package.json, it also doesn't work.

Both of my packages are not published on npmjs, I only have them on my local machine because both are still in development. But it seems npm isn't made for development, it's just good for consumption of already published packages.

Perhaps it may help to check if the filesystem links are created as expected.

You can check which is the global npm directory by typing npm root -g in your terminal

Then change to npm global root directory and type ls -al to see the links. In my case, for instance:

Is the library my-client installed globally? Or its it a file relative to your node red node project?

As a test, try using the full path of my-client.js. I strongly suspect this is a relative path issue. You need the correct ..\\foldername\\ relative path

1 Like

The packages should be installed correctly. As far as I understood npm's behaviour with installations from local directories, the links are set up as expected. Under ~/.node-red/node_modules there are two links now: node-red-contrib-my-client pointing to the development directory of that package, which includes node_modules and another link to my-client's development directory, and additionally the my-client link directly for node-red.

The packages are not installed globally, just locally for node-red.

What did work is altering the require call to this:

//var MyClient = require("my-client");   // Should be correct
var MyClient = require("../my-client/my-client");   // Works instead

I guess this will fail when I publish my packages and have them installed from npmjs.

The package my-client (used by node-red-contrib-my-client) has another dependency to @ygoe/msgpack which is already published on npmjs. That package has not caused any trouble whatsoever. And it's not installed for node-red directly, it just appears in node_modules/node-red-contrib-my-client/node_modules/my-client/node_modules/@ygoe/msgpack as well as node_modules/my-client/node_modules/@ygoe/msgpack (because these are linked together). It seems Node.js can't properly handle packages that are not installed from npmjs.

It is not easy to understand the issue without knowing the exact structure of your directories.

As explained in below link Node.JS will check if your package (my-client) is installed in /node_modules of the parent directory. If it is not found it will check /node_modules directories all the way up to the root directory.

## Loading from node_modules Folders

When you use '../' you are overriding the search algorithm and telling Node.JS explicitly where to find the package.

That's what I intended. The ../ path was to try and override the search. But the search should actually find the package, too, if it starts in the right location. I guess it doesn't. I'm going to create a simple test case with Node.js only, without node-red, and try to find support for that.