How to debug Function "Error: Module not allowed"

Hello All!

I am working with function nodes and trying to import several different js modules with varying success. This one has me rather stumped.

warpjs, a tool for manipulating SVGs. It acts like it loads then says it is not allowed. There is not any other information I seem to find to give me any idea why. I have an older 3.0.2 NR version with 16.x node.js and had warpjs installed without error (although not yet implemented).

NodeRed v4.03
node.js tried 18 and 20 same result.
settings.js is stock

How can I determine what is at the core of the rejection?

5 Oct 06:12:06 - [info] Installing module: warpjs, version: latest
5 Oct 06:12:14 - [info] Installed module: warpjs
5 Oct 06:12:14 - [info] Starting flows
5 Oct 06:12:15 - [error] [function:0dea637d61d8eab4] Error: Module not allowed

I have no problem in loading warpjs.
So how are you actually loading it in a function node?

But also, looking at the repo - its meant to be used on the DOM no?, not server side - therefore won't work in a flow?

I ask, as the constructor is asking for a DOM element

Could be wrong of course

[{"id":"d4f72602eb0aee8b","type":"function","z":"2d7bf6e3.84c97a","name":"function 3","func":"return {payload:{warpjs:warpjs.toString()}}","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"warpjs","module":"warpjs"}],"x":400,"y":1820,"wires":[["d27d62f20acc64e8"]]},{"id":"1e28ce1d1e835ff5","type":"inject","z":"2d7bf6e3.84c97a","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":1820,"wires":[["d4f72602eb0aee8b"]]},{"id":"d27d62f20acc64e8","type":"debug","z":"2d7bf6e3.84c97a","name":"debug 394","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":590,"y":1820,"wires":[]}]

Thanks for taking a look.

I am loading it the same as you did in to the setup tab of the function.

When I tried your sample, it gives me the same rejection notice.

Which version of NR and nodejs are you running (I too get it to run in older versions)?

Regarding the DOM needed or not, I have not fully tested the workflow to make sure there are not other issues. I think it will work with the path only data of an svg, but if not, I am also trying to get svgDOM working within NR as it is a headless approach. That is another quirky integration of its own.

Thanks. That is what I was thinking it could do. From that information, I would expect it to work outside of the browser for my needs. I am only needing it for path alteration, not DOM work.

Do you have any idea why it might be "not allowed" in the current 4.03 NR?

Or any idea where I might find general info on how to determine if a module is compatible with NR in general?

I have an assortment of modules I have been testing with varying results. Some work without a hitch, some rejected as with warpjs, then others that only work half the time as with svgDOM for example. I would like to avoid wasting anyone's time if I could just figure out both how to determine if a module is compatible and how to debug/determine what needs to be revised to allow it to be compatible on my own.

thanks again

As already demonstrated by @marcus-j-davies there is no reason it should not work.

The only setting that prevents modules loading is in the settings.js file under externalModules.modules.denyList

In general, if the module is well defined, it should be installable. Depending on how the module exports its definition (Common JS, ESM, UMD, other) will determine how you use it (or if possible at all). Typically all CJS will work. For the others, it depends...

Based on your comments and talk of SVG and DOM, you are in for a rough ride trying to do this server side (in a function node, AKA in nodejs not Browser). There are some libraries that mimic the browser DOM like jsDOM but from my experience, SVG is not well supported (for example SVGGraphicsElement: getBBox() typically either doesnt work or returns 0) however, depending on what you are tryng to achieve, that might be enough.

Thanks Steve.

I wasn't sure which version marcus was running to have success. The 3.x setup I have runs fine, while the 3.x upgraded to 4.x did not. I started trying to revert my 4.x to older versions as a forensic test to see which version started giving me trouble, but I hit it with too big of a hammer and somehow corrupted the install. I started over with a fresh rpi 4 OS and node red install to the current of everything, and it runs warpjs as it should. I don't know if the upgrade from 3 to 4 had some issue, or if other combined stuff was the culprit, but it does look like something was bad with my system.

I will educate myself on the different module definitions you mentioned. That should help for troubleshooting the other modules that do not fully run.

Regarding svg work in nodejs instead of browser, my application is a 2 axis CNC controller. The svg work is path only. I am bringing in svg files/paths and allowing the user to make some edits via dashboard where I will apply changes in function nodes. At least that is what I am working on for now. It looks like I can get there from here, with a little bit of pain, to prove everything out and get to the next phase.

Thanks for all the help!

1 Like

@Steve-Mcl
Having fun here digging in the rabbit hole. Even though the warpjs developer says he intended to keep a lot of the DOM related code separated, it calls a query right away that stops the action. For those that may find this and do not need the full functionality of what warpjs can do, I did find an updated yet stripped version that works server side in NR here @remotion/paths

My current approach is to go ahead and clear the warpjs module of DOM stuff and load it locally. After much failed searching, I could not find current details on a few related nuggets. I hope you may be able to enlighten me on the answers or point out any documentation to shed some light.

  • I looked in ".node-red/node_modules" and did not see any of the modules I have been testing from within the function setup tab. Where does the NR 4.x store user external modules on an rpi install?

  • Where should a local, not npm installed, module be stored and what is the proper syntax for the function setup tab to load it?

Thank you!

The function node setup tab depends on modules from the NPM registry.

Instead, you will need to use the older method of functionGlobalContext (docs: Writing Functions : Node-RED)

So in your case (some assumptions made)

in your settings.js, locate functionGlobalContext,uncomment it, add your reference(s)

...
functionGlobalContext: {
    mySvgModule: require('my-modules/svg_stuff.js') // probably wise to keep stuff relative to .node_red
}
...

then in a function node

const mySvgModule = global.get('mySvgModule')

Thank you! I was thinking I could use the setup in function to load modules. I didn't realize the functionGlobalContext was the appropriate method.

I am still trying to get it to see my module, which for some error on my part it is not, and in trying I noticed that the function does not throw an error if the required module does not exist. For example, I can use your literal note in the function and it will not error that mySvgModule does not exist.

If it does not exist then mySvgModule will be undefined.

require will (should) throw MODULE_NOT_FOUND which would crash Node-RED on start up so I suspect it is working. Or, you edited the wrong settings file and you are not really loading the module. Try putting console.logs in the module.

Also,

Is your module actually exporting anything?

Is you function doing anything other than const mySvgModule = global.get('mySvgModule')?

EDIT:
It may seem obvious to me but i will also state for clarity, you must restart node-red for it to load the settings file (and thus load your module)

I did an npm install in the .node-red directory of the existing module I want to start modifying. It added it to the expected .node-red/node_modules directory. I don't know if starting off this way made a mess already.

Undefined, yes. That is what I see. I was assuming an error would be thrown.

@Steve-Mcl Even with using completely random global.get parameters, not seeing any errors and NR is not crashing. I have restarted NR and after every settings.js change.

.node-red/settings.js file... should it be the /usr/lib/node_modules/node-red/settings.js?

edit: My function initially, yes. Since it was not acting happy, I made a new function with only that line and sent mySvgModule to payload and saw it was undefined.
The module is the warpjs module I am trying to start editing.

No.

The settings file is displayed in your start up log when you start node-red.

You should undo edits to this file. This is the NR source & it will/can affect future instances of node-red.

thats not what I said. i said:

i.e. using require is a settings file thing - nothing to do with global.get

Yes yes. My bad. I had also tested making bad module names and locations in settings.js at the require statements and it didn't seem to care. I jumbled two post thoughts into one mess. Sorry.

Did I miss a module loading permission somewhere that is keeping NR from looking at the functionGlobalContext?

It wont. you are editing the wrong file

These are several attempts in editing the settings.js listed in NR startup log. All of them allow NR to start without any mention of trouble that I am seeing.

>    functionGlobalContext: {
>         //Warp:require('warpjs')
>         //warpit:require('warp.js')
>         //warpit:require('node_modules/warpjs/src/Warp.js')
>         warpit:require('node_modules/warpjs')
>         // os:require('os'),
>     },

Startup:

testpi@testpi:~ $ sudo node-red start
14 Oct 06:05:22 - [info]

Welcome to Node-RED

14 Oct 06:05:22 - [info] Node-RED version: v4.0.3
14 Oct 06:05:22 - [info] Node.js version: v20.18.0
14 Oct 06:05:22 - [info] Linux 6.6.51+rpt-rpi-v8 arm64 LE
14 Oct 06:05:22 - [info] Loading palette nodes
14 Oct 06:05:23 - [info] Settings file : /root/.node-red/settings.js
14 Oct 06:05:23 - [info] Context store : 'default' [module=memory]
14 Oct 06:05:23 - [info] User directory : /root/.node-red
14 Oct 06:05:23 - [warn] Projects disabled : editorTheme.projects.enabled=false
14 Oct 06:05:23 - [info] Flows file : /root/.node-red/start
14 Oct 06:05:23 - [info] Server now running at http://127.0.0.1:1880/
14 Oct 06:05:23 - [warn]


Your flow credentials file is encrypted using a system-generated key.

If the system-generated key is lost for any reason, your credentials
file will not be recoverable, you will have to delete it and re-enter
your credentials.

You should set your own key using the 'credentialSecret' option in
your settings file. Node-RED will then re-encrypt your credentials
file using your chosen key the next time you deploy a change.

14 Oct 06:05:23 - [info] Starting flows
14 Oct 06:05:24 - [info] Started flows

test nodes

[
    {
        "id": "6241f6afe031be07",
        "type": "function",
        "z": "5a1c05cfa61f358b",
        "name": "testing warp local edit",
        "func": "const warpit = global.get('warpit');\n\nvar path_data = msg.payload;\n//node.warn(path_data);  \n\nvar bpoints = msg.bpoints;\n//node.warn(bpoints);\n\nvar buffers = msg.buffers;\n//node.warn(buffers);\n\nconst newWarp = new warpit.Warp(path_data);\n//const warp = new Warp(path_data);\n//warp.interpolate(4);\nconsole.log(newWarp);\n\nreturn msg;\n\n\n\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 560,
        "y": 220,
        "wires": [
            [
                "21ad1bc9baee811e"
            ]
        ]
    },
    {
        "id": "f20d4b2c05b41614",
        "type": "inject",
        "z": "5a1c05cfa61f358b",
        "name": "send path and related items",
        "props": [
            {
                "p": "payloadBak",
                "v": "m 184.2467,188.12341 c 44.8042,75.2293 23.9557,136.2636 2.9041,197.2539 33.6155,0.7488 57.9452,9.2357 69.6959,28.2051 77.6344,-16.691 158.3988,-21.3838 243.7611,-8.451 5.4947,-22.4815 22.8346,-33.1177 50.202,-33.7265 -16.0787,-55.175 -15.9528,-111.2503 0.7826,-168.2484 -32.2574,-6.2921 -46.0524,-17.8593 -52.9118,-31.408 -90.3634,14.7499 -168.8152,12.9559 -235.9759,-4.5202 -12.8294,22.5088 -44.0061,23.6124 -78.458,20.8951 z m 97.2131,48.6065 c 10.9275,34.3061 10.0291,68.098 0,101.4929 9.6764,3.4293 15.7051,-2.1456 34.6918,16.0547 44.0821,-8.9789 87.4855,-9.8125 130.2786,-3.3237 7.3855,-11.2446 17.1483,-17.3387 30.0007,-16.7384 -14.7552,-39.7283 -8.4853,-67.776 1.0561,-94.0062 -14.2136,-0.075 -30.1115,2.3763 -33.8385,-13.4286 -40.5067,7.2913 -81.3049,10.2087 -123.0916,-1.7001 -10.7014,9.0112 -23.8387,12.6636 -39.0971,11.6494 z M 760.9055,98.50001 c -83.2566,41.6283 -169.879,22.6377 -188.9764,0 -134.6849,36.6568 -262.3433,36.2632 -377.9527,0 -25.6735,18.9245 -110.229,39.3737 -188.9764,0 m 0,377.9527 c 53.8364,-26.9182 141.8086,-26.0881 188.9764,0 125.9842,-24.2128 251.9685,-22.175 377.9527,0 30.5695,-17.6559 126.5304,-31.223 188.9764,0 m 0,-377.9527 c -59.7865,89.3616 -53.791,287.748 0,377.9527 M 5,98.50001 c 73.3677,98.4953 59.402,267.9253 0,377.9527 M 571.9291,98.50001 c -24.02924,23.83578 -46.73642,45.68846 -73.2485,73.2485 -17.61007,17.85472 -33.63581,34.65323 -55.0321,55.0321 -19.23437,18.23688 -40.18594,39.90815 -60.6957,60.6958 -21.98354,21.84175 -42.37299,41.29235 -66.8012,66.8011 -19.7683,18.14107 -39.5366,37.10542 -59.3049,59.3049 -25.3056,23.13118 -42.44173,42.17763 -62.8703,62.8703 m 0,-377.9527 c 21.52641,22.54134 43.17954,44.87829 68.7283,68.7283 18.78942,19.77871 37.71897,39.4173 57.8522,57.8522 19.81168,17.83776 41.30205,40.7116 62.3959,62.3959 20.83002,21.48825 41.35243,43.28411 63.4774,63.4774 17.0615,18.0592 35.84083,36.1184 54.1776,54.1776 22.68513,19.41921 47.41754,47.02754 71.3213,71.3213 M 760.9055,98.50001 c -69.77103,34.98098 -139.54207,70.88613 -209.3131,104.6565 -24.39015,12.50672 -47.26094,25.77313 -74.1054,37.0527 -30.55536,14.7997 -61.29864,29.7873 -94.5342,47.2672 -33.3489,16.43336 -65.62288,31.79181 -101.493,50.7464 -29.38654,14.89825 -58.31252,29.61228 -94.309,47.1545 C 130.73511,413.58515 66.315726,445.79485 5,476.45271 M 5,98.50001 c 59.404627,31.25156 118.54165,63.57355 179.2467,89.6234 31.83175,15.91586 62.82393,31.41193 97.2131,48.6065 33.831,17.98491 67.662,33.98982 101.493,50.7465 30.40109,15.57967 60.45235,31.15933 93.4781,46.739 24.79297,13.30977 49.58593,25.20118 74.3789,37.1895 70.0319,36.09433 140.0638,70.17688 210.0957,105.0478",
                "vt": "str"
            },
            {
                "p": "bpoints",
                "v": "[[22,22],[5,220],[100,240],[350,180],[520,210],[500,20],[350,-40],[190,35]]",
                "vt": "json"
            },
            {
                "p": "buffers",
                "v": "{\t 'top': 0.1,\t 'bottom': 0.2,\t 'left': 0.3,\t 'right': 0.4\t}",
                "vt": "jsonata"
            },
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "<path d='m 184.2467,188.12341 c 44.8042,75.2293 23.9557,136.2636 2.9041,197.2539 33.6155,0.7488 57.9452,9.2357 69.6959,28.2051 77.6344,-16.691 158.3988,-21.3838 243.7611,-8.451 5.4947,-22.4815 22.8346,-33.1177 50.202,-33.7265 -16.0787,-55.175 -15.9528,-111.2503 0.7826,-168.2484 -32.2574,-6.2921 -46.0524,-17.8593 -52.9118,-31.408 -90.3634,14.7499 -168.8152,12.9559 -235.9759,-4.5202 -12.8294,22.5088 -44.0061,23.6124 -78.458,20.8951 z m 97.2131,48.6065 c 10.9275,34.3061 10.0291,68.098 0,101.4929 9.6764,3.4293 15.7051,-2.1456 34.6918,16.0547 44.0821,-8.9789 87.4855,-9.8125 130.2786,-3.3237 7.3855,-11.2446 17.1483,-17.3387 30.0007,-16.7384 -14.7552,-39.7283 -8.4853,-67.776 1.0561,-94.0062 -14.2136,-0.075 -30.1115,2.3763 -33.8385,-13.4286 -40.5067,7.2913 -81.3049,10.2087 -123.0916,-1.7001 -10.7014,9.0112 -23.8387,12.6636 -39.0971,11.6494 z M 760.9055,98.50001 c -83.2566,41.6283 -169.879,22.6377 -188.9764,0 -134.6849,36.6568 -262.3433,36.2632 -377.9527,0 -25.6735,18.9245 -110.229,39.3737 -188.9764,0 m 0,377.9527 c 53.8364,-26.9182 141.8086,-26.0881 188.9764,0 125.9842,-24.2128 251.9685,-22.175 377.9527,0 30.5695,-17.6559 126.5304,-31.223 188.9764,0 m 0,-377.9527 c -59.7865,89.3616 -53.791,287.748 0,377.9527 M 5,98.50001 c 73.3677,98.4953 59.402,267.9253 0,377.9527 M 571.9291,98.50001 c -24.02924,23.83578 -46.73642,45.68846 -73.2485,73.2485 -17.61007,17.85472 -33.63581,34.65323 -55.0321,55.0321 -19.23437,18.23688 -40.18594,39.90815 -60.6957,60.6958 -21.98354,21.84175 -42.37299,41.29235 -66.8012,66.8011 -19.7683,18.14107 -39.5366,37.10542 -59.3049,59.3049 -25.3056,23.13118 -42.44173,42.17763 -62.8703,62.8703 m 0,-377.9527 c 21.52641,22.54134 43.17954,44.87829 68.7283,68.7283 18.78942,19.77871 37.71897,39.4173 57.8522,57.8522 19.81168,17.83776 41.30205,40.7116 62.3959,62.3959 20.83002,21.48825 41.35243,43.28411 63.4774,63.4774 17.0615,18.0592 35.84083,36.1184 54.1776,54.1776 22.68513,19.41921 47.41754,47.02754 71.3213,71.3213 M 760.9055,98.50001 c -69.77103,34.98098 -139.54207,70.88613 -209.3131,104.6565 -24.39015,12.50672 -47.26094,25.77313 -74.1054,37.0527 -30.55536,14.7997 -61.29864,29.7873 -94.5342,47.2672 -33.3489,16.43336 -65.62288,31.79181 -101.493,50.7464 -29.38654,14.89825 -58.31252,29.61228 -94.309,47.1545 C 130.73511,413.58515 66.315726,445.79485 5,476.45271 M 5,98.50001 c 59.404627,31.25156 118.54165,63.57355 179.2467,89.6234 31.83175,15.91586 62.82393,31.41193 97.2131,48.6065 33.831,17.98491 67.662,33.98982 101.493,50.7465 30.40109,15.57967 60.45235,31.15933 93.4781,46.739 24.79297,13.30977 49.58593,25.20118 74.3789,37.1895 70.0319,36.09433 140.0638,70.17688 210.0957,105.0478' style='fill:none;stroke:#000000' />",
        "payloadType": "str",
        "x": 280,
        "y": 220,
        "wires": [
            [
                "6241f6afe031be07"
            ]
        ]
    },
    {
        "id": "21ad1bc9baee811e",
        "type": "debug",
        "z": "5a1c05cfa61f358b",
        "name": "debug 401",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 790,
        "y": 220,
        "wires": []
    }
]

Please clarify which file you are editing.

At first you said:

So that could be .node-red/settings.js or /usr/lib/node_modules/node-red/settings.js

You have not stated which and also, the first is a relative path (it could be anywhere).

The EXACT and complete path is listed in your settings file...

... that one :point_up: (in the /root** dir) is what you should edit.


** running node-red as root is not advised and most often NOT necessary!
Unless it is a conscious decision and for a required reason & all possible security measures have been taken, you should NOT start node-red with sudo or an administrative/privileged account.