Catching errors in `subflow` - more help please

I did a bit of digging and it paid off.

(extract from code used:)

if (typeof msg.delay === "undefined")
{
    const id  = env.get("NR_NODE_PATH");
    const ids = id.split("/");
    const errr = `msg.delay not set in message going into ${ids[1]}`;
    node.error(errr, msg);
    msg.source = ids[1];
    return;
}

Which is all well and good for THAT instance and THAT error.

So it now begs the question to me:
How do I catch errors in a subflow and pass on the error to the parent flow so the *parent flow's error message points to the subflow node.

I'm not sure how it will work with this node already managing it's own errors.

Could I just negate this part and handle all errors with the catch node in the subflow?
Would make it easier.
:slight_smile:

I've kinda done it, but the formatting is not the best and I just get a message with the dummy error message and the node's number all in one line.

How would I format it so the node number is per real error messages?
And maybe pass on the whole error message too?
(Trying ITMT)

Update:

This is a test flow I made to check.

Thoughts?

[{"id":"089874d72f82b238","type":"subflow","name":"Error handler for subflows","info":"2024 06 17\n==========\n\nBasic overview.\n`TEST node` causes an error.\n(any input)\n\n`Upsend error message` relays the\nerror message to the parent flow.\n`error.source` -> subflow with error\n`_error.source.name` -> name of node that\ncaused the error.\n`_error.message` -> the error message\n\nSuggestion:\n-----------\nThe `catch` node should only catch\nerrors from `function` nodes.\n","category":"","in":[{"x":230,"y":70,"wires":[{"id":"18bb902b0b89f912"}]}],"out":[{"x":360,"y":190,"wires":[{"id":"830e5e8780badf3b","port":0}]}],"env":[],"meta":{},"color":"#DDAA99"},{"id":"18bb902b0b89f912","type":"function","z":"089874d72f82b238","name":"TEST node","func":"node.error(\"Error\",msg)","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":410,"y":70,"wires":[[]]},{"id":"830e5e8780badf3b","type":"catch","z":"089874d72f82b238","name":"","scope":["18bb902b0b89f912"],"uncaught":false,"x":200,"y":190,"wires":[["06b515199b7eb047"]]},{"id":"06b515199b7eb047","type":"function","z":"089874d72f82b238","name":"Upsend error message","func":"const id  = env.get(\"NR_NODE_PATH\");\nconst ids = id.split(\"/\");\nconst errr = `Something went wrong in subflow (See source number below).\\nopen the _error.source object (below) to get more details`;\nmsg.source = ids[1];\nnode.error(errr, msg);\n    \n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":240,"wires":[[]]},{"id":"52cc9476d774b429","type":"subflow:089874d72f82b238","z":"7e987ddf260bdf0d","name":"","x":420,"y":3410,"wires":[["58bd64507cef17b7"]]},{"id":"897d573b21452c75","type":"inject","z":"7e987ddf260bdf0d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":170,"y":3410,"wires":[["52cc9476d774b429"]]},{"id":"58bd64507cef17b7","type":"debug","z":"7e987ddf260bdf0d","name":"Used for testing.","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":860,"y":3410,"wires":[]},{"id":"a28a91a006a4fee5","type":"catch","z":"7e987ddf260bdf0d","name":"","scope":["52cc9476d774b429"],"uncaught":false,"x":360,"y":3510,"wires":[["2257c395145111bb","ffcfe59eeec7ec81"]]},{"id":"2257c395145111bb","type":"debug","z":"7e987ddf260bdf0d","name":"Ok error message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":870,"y":3450,"wires":[]},{"id":"ffcfe59eeec7ec81","type":"change","z":"7e987ddf260bdf0d","name":"","rules":[{"t":"move","p":"_error.source","pt":"msg","to":"error.source","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":3510,"wires":[["2acd17e7327bb6bc"]]},{"id":"2acd17e7327bb6bc","type":"debug","z":"7e987ddf260bdf0d","name":"Better error message","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":880,"y":3510,"wires":[]}]

It seems to me that if an error occurs in a subflow it's useful for that node to raise an error message in the debug pane. However it gives no indication of which flow called the subflow and caused the error.

I don't use subflows much but if I did I would set a policy of always testing for msg.error in the subflow output.

[{"id":"35e0cbf557489b94","type":"subflow","name":"Convert oz to g","info":"","category":"","in":[{"x":280,"y":80,"wires":[{"id":"35b905044e421edf"}]}],"out":[{"x":520,"y":80,"wires":[{"id":"35b905044e421edf","port":0}]}],"env":[],"meta":{},"color":"#DDAA99"},{"id":"35b905044e421edf","type":"function","z":"35e0cbf557489b94","name":"function 1","func":"if (typeof msg.payload != \"number\") {\n    msg.error = \"No valid ounces value received\"\n    node.error(\"Bad input data\")\n}\nelse {\n    msg.payload = msg.payload * 28.34949\n}\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":400,"y":80,"wires":[[]]},{"id":"8c20323b911f6b0e","type":"inject","z":"a847a62177aa3eb7","name":"Good data - number","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"16","payloadType":"num","x":130,"y":80,"wires":[["07f0f1c64feada9a"]]},{"id":"07f0f1c64feada9a","type":"subflow:35e0cbf557489b94","z":"a847a62177aa3eb7","name":"","x":340,"y":100,"wires":[["a4e6ab74fc44acb2"]]},{"id":"5f5172ff34f848ef","type":"debug","z":"a847a62177aa3eb7","name":"Good conversion - Grams","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":730,"y":80,"wires":[]},{"id":"1d45b002d145855a","type":"inject","z":"a847a62177aa3eb7","name":"Bad data - string","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"16","payloadType":"str","x":120,"y":120,"wires":[["07f0f1c64feada9a"]]},{"id":"a4e6ab74fc44acb2","type":"switch","z":"a847a62177aa3eb7","name":"msg.error?","property":"error","propertyType":"msg","rules":[{"t":"null"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":510,"y":100,"wires":[["5f5172ff34f848ef"],["adab2f4de69d3a1c"]]},{"id":"adab2f4de69d3a1c","type":"debug","z":"a847a62177aa3eb7","name":"Error message","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"error","targetType":"msg","statusVal":"","statusType":"auto","x":700,"y":120,"wires":[]}]

This is the output if I pass a valid number to the subflow
image

And here is the result of passing a string
image

1 Like

Thanks.

That's an interesting approach to it.

In fact a subflow can have two outputs, one for good data, one for error notifications. So I could dispense with the switch node
image

image

1 Like

So the second output is just the direct output from the internal catch node?

I'm only saying/asking about it because I have error catching routines on all my flows - in the production machines - to help handle errors.

Well not in that example.
I don't have a catch node because I'm happy to see an error message in the debug.
After all an error occurred; I see no value in making it less obvious.

Instead the function in my simple subflow has two outputs which are directed to the relevant output from the subflow.

I think this approach relies on the fact that a node.error() call does not halt further processing in a function node.

Generally speaking my flows are not as complex as yours. My ideas might well be inappropriate for your production algorithms.

Ok, thanks.

We may be on different pages on the workings. But that's ok.

I'm trying to get a bigger picture of how to do this so if it is a complicated subflow and an error happens, I can get the subflow name/number - to identify it from all other instances of it - and the actual error the subflow created.

I think my way the original error is held in the _error part of the message.

Thanks though. It is sometimes good to look at it from a different point of view.

And yes, alas my flows are a bit scary)