Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Put function node in try catch #4661

Closed
carefulcomputer opened this issue Apr 18, 2024 · 4 comments
Closed

Put function node in try catch #4661

carefulcomputer opened this issue Apr 18, 2024 · 4 comments

Comments

@carefulcomputer
Copy link

Current Behavior

When a function node throws uncaught exception node-red crashes.

Expected Behavior

When a function node throws uncaught exception node-red should log the error and not crash.

Steps To Reproduce

have a function node throw uncaught exception.

Example flow

No response

Environment

  • Node-RED version: 3.1.9
  • Node.js version:20.x
  • npm version:
  • Platform/OS: apline docker
  • Browser: chrome
@Steve-Mcl
Copy link
Contributor

Throwing errors in a function node do not crash node-red unless the error is occurring in an async function.

You can test this yourself with a simple function:

throw new Error('does node red crash?")

Here is some proof:
WindowsTerminal_9KdSy1jXVo

[{"id":"d8777424e868d0da","type":"inject","z":"85fb8b6df2be7ac8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1280,"y":60,"wires":[["797fe9ac0a832c30"]]},{"id":"797fe9ac0a832c30","type":"function","z":"85fb8b6df2be7ac8","name":"throw an error","func":"throw new Error('did node-red crash?')\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1500,"y":60,"wires":[[]]},{"id":"b4cc4bb3edaf2698","type":"function","z":"85fb8b6df2be7ac8","name":"throw an error in callback","func":"\nsetTimeout(function() {\n    throw new Error('did node-red crash?')    \n}, 10);\n\n\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1530,"y":120,"wires":[[]]},{"id":"e239976943cfe43f","type":"inject","z":"85fb8b6df2be7ac8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1280,"y":120,"wires":[["b4cc4bb3edaf2698"]]},{"id":"9e39161661fd0134","type":"inject","z":"85fb8b6df2be7ac8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1280,"y":180,"wires":[["4695944cf538b803"]]},{"id":"4695944cf538b803","type":"function","z":"85fb8b6df2be7ac8","name":"throw an error in async callback","func":"\nsetTimeout(async function() {\n    throw new Error('did node-red crash?')    \n}, 10);\n\n\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1550,"y":180,"wires":[[]]}]

A node application crashing on uncaught exceptions is the correct behaviour since uncaught exceptions indicate that the application is in an undefined state.

In short, this is down to the user programming. Here is a recent example of this: https://discourse.nodered.org/t/nodered-container-crash-everyday/86933/7?u=steve-mcl

@knolleary
Copy link
Member

A node application crashing on uncaught exceptions is the correct behaviour since uncaught exceptions indicate that the application is in an undefined state.

Just to reiterate what Steve said, this is specifically related to uncaught exceptions in an async callback function. By their very nature, they cannot be handled by a try/catch in the Function node. Similarly, when they do occur, we have no way of identifying which node (Function node or otherwise) led to the async exception happening. This is just how Node.js works and not something we can work around.

Can you provide an example of your code that is causing Node-RED to crash?

@carefulcomputer
Copy link
Author

First of all thanks for responding so fast. I really appreciate all the work you do. And you are right, it was an async web call using axios in function node. It was a user (me) error for not handling the axios errors. I am wondering if there is any way to not let whole node-red to crash in case of boo-boos made by users ? apologies, I am not an experienced nodejs programmer so it may may be a dumb idea, but could node-red wrap function node in async await and catches the error at wrapper ? something like this where "run" function is a node-red wrapper over user created function node "thisThrows".

async function thisThrows() {
    throw new Error("Thrown from thisThrows()");
}

async function run() {
    try {
        await thisThrows();
    } catch (e) {
        console.error(e);
    } finally {
        console.log('We do cleanup here');
    }
}

run();

@knolleary
Copy link
Member

I am wondering if there is any way to not let whole node-red to crash in case of boo-boos made by users ?

Its a tough one. The node.js docs themselves recommend not trying to recover from an uncaught exception because you simply don't know what failed and what state anything is in - restarting the runtime is the safest action to take.

We are pretty much reliant on what node.js provides us in terms of capturing and logging such errors - and there isn't a lot more we can do.

I'm going to close this issue off as we don't have any immediate actions to take here. But this is a general topic we keep an eye on in case node.js introduces anything that could help us.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants