Capturing errors caused inside link-call flows

Hi There!

I'm wondering what is the best way of capturing errors that are raised within the flow of a link-call?

Example flow:

[{"id":"2bd6810d.e22ece","type":"catch","z":"da728ee9d651fde8","name":"","scope":["2c94a22c.91012e"],"uncaught":false,"x":791,"y":539,"wires":[["ea01375bb63004ca"]]},{"id":"2c94a22c.91012e","type":"function","z":"da728ee9d651fde8","name":"Throw Error","func":"node.error(\"an example error\", msg);   ","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":805,"y":454,"wires":[["ea01375bb63004ca"]]},{"id":"72517b3dadec43f9","type":"link in","z":"da728ee9d651fde8","name":"link in 2","links":[],"x":518,"y":370,"wires":[["2c94a22c.91012e"]]},{"id":"ea01375bb63004ca","type":"link out","z":"da728ee9d651fde8","name":"link out 79","mode":"return","links":[],"x":1094,"y":337,"wires":[]},{"id":"a957d4a801015562","type":"link call","z":"da728ee9d651fde8","name":"","links":["72517b3dadec43f9"],"linkType":"static","timeout":"4","x":1366,"y":666,"wires":[["f303e4920a752c2c"]]},{"id":"a1324180ccb5429d","type":"inject","z":"da728ee9d651fde8","name":"Trigger error","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1161,"y":633,"wires":[["a957d4a801015562"]]},{"id":"eee84a44f3b6bb69","type":"catch","z":"da728ee9d651fde8","name":"","scope":["a957d4a801015562","f303e4920a752c2c"],"uncaught":false,"x":1378,"y":733,"wires":[["1d0da1cc549ad8f3"]]},{"id":"1d0da1cc549ad8f3","type":"debug","z":"da728ee9d651fde8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1774,"y":659,"wires":[]},{"id":"495237ede246b15d","type":"debug","z":"da728ee9d651fde8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1801,"y":467,"wires":[]},{"id":"f303e4920a752c2c","type":"function","z":"da728ee9d651fde8","name":"detect error","func":"if ( msg.error ) {\n    node.error(\"error detected\", msg)\n} else {\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1565,"y":566,"wires":[["495237ede246b15d"]]}]

The link in 2 link call node calls the Throw Error function which throws the error. The error is normally captured by the catch: 1 catch node and passed out by the link-out node to which it is connected. Otherwise the error does not find its way back to the link call node. That is, if the error thrown by the Throw Error function isn't caught, it disappears into the ether and the link call node times out.

But I want the original error thrown by the function node Throw Error so I've caught it and passed it out. Now I would like the link in 2 link-call node to re-throw the error but it doesn't. Instead I've added a detect error function that throws an error if the error property is set on the msg, its code:

if ( msg.error ) {
    node.error("error detected", msg)
} else {
    return msg;
}

Using this setup, I come out at the catch: 2 catch node and over to the (bottom) msg debug node. That's what I want. Is there an easier way to do this? I don't really want to have a detect error function node after all my link-call nodes.

What I want is something like this:

With the same affect that I come out at the bottom debug node... is that possible with some magic settings or is there no way of doing it? I understand that the link out node isn't reached when the error is raised but if I add the catch that is connected to the link out node, then the msg (containing the error) is handled as a normal msg and the top debug node is reached, i.e., I would wish that the link-call node detects the error property on the message and throws an error as a result.

My goal is to get the original error object and not a timeout error that will be raised by the link-call if the link-out node isn't reached ... which is the case presently.

Sorry if this has been answered elsewhere ...

Cheers!

Edit: just noticed that if the Throw Error function node has a node.status({...}) update, that isn't passed to the link-call node either. It's shown on the Throw Error function node but not on the calling link-call node. Ideally each link-call node would be assigned the status that the original node generated but if the flow consists of many nodes, all with their own status updates, which would be passed to the link-call node? Hm.

1 Like

Strange behaviour, but if you do node.error(msg) you can capture OG error and not get a timeout. Just no error text message is shown.
e.g.

[{"id":"a1324180ccb5429d","type":"inject","z":"b9860b4b9de8c8da","name":"Trigger error","props":[{"p":"payload","v":"","vt":"date"},{"p":"topic","v":"","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":3440,"wires":[["a957d4a801015562"]]},{"id":"a957d4a801015562","type":"link call","z":"b9860b4b9de8c8da","name":"","links":["72517b3dadec43f9"],"linkType":"static","timeout":"4","x":300,"y":3440,"wires":[["f303e4920a752c2c"]]},{"id":"f303e4920a752c2c","type":"function","z":"b9860b4b9de8c8da","name":"detect error","func":"if (msg.error) {\n    node.error(msg)\n} else {\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":3440,"wires":[["495237ede246b15d"]]},{"id":"495237ede246b15d","type":"debug","z":"b9860b4b9de8c8da","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":590,"y":3520,"wires":[]},{"id":"72517b3dadec43f9","type":"link in","z":"b9860b4b9de8c8da","name":"link in 2","links":[],"x":295,"y":3260,"wires":[["2c94a22c.91012e"]]},{"id":"2c94a22c.91012e","type":"function","z":"b9860b4b9de8c8da","name":"Throw Error","func":"node.error(\"an example error\", msg);   ","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":404,"y":3255,"wires":[["ea01375bb63004ca"]]},{"id":"ea01375bb63004ca","type":"link out","z":"b9860b4b9de8c8da","name":"link out 79","mode":"return","links":[],"x":515,"y":3260,"wires":[]},{"id":"2bd6810d.e22ece","type":"catch","z":"b9860b4b9de8c8da","name":"","scope":["2c94a22c.91012e"],"uncaught":false,"x":430,"y":3320,"wires":[["ea01375bb63004ca"]]}]

Sorry that's not what I want, my goal is this:

I have several link-call nodes chained together and if one of the fails, then the single catch node should capture it. The variation you posted would continue down the flow if an exception happened inside the link-call node.

That works fine if you only have one link-call node :wink:

Hence me wondering whether the link-call node could throw/raise/trigger the error of the flow it called if there is an msg object returned that contains an error attribute.

In that case then, without recoding the link call node you could capture the error and the timeout, which gives you the error, OG msg and the link call that called the function.
e.g.

[{"id":"a1324180ccb5429d","type":"inject","z":"b9860b4b9de8c8da","name":"Trigger error","props":[{"p":"payload","v":"","vt":"date"},{"p":"topic","v":"","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":170,"y":3300,"wires":[["bdac6f397f10a48c"]]},{"id":"bdac6f397f10a48c","type":"link call","z":"b9860b4b9de8c8da","name":"link1","links":["72517b3dadec43f9"],"linkType":"static","timeout":"4","x":210,"y":3340,"wires":[["a957d4a801015562"]]},{"id":"a957d4a801015562","type":"link call","z":"b9860b4b9de8c8da","name":"link 2","links":["72517b3dadec43f9"],"linkType":"static","timeout":"4","x":370,"y":3340,"wires":[["1bb158698ba06402"]]},{"id":"1bb158698ba06402","type":"link call","z":"b9860b4b9de8c8da","name":"link 3","links":["72517b3dadec43f9"],"linkType":"static","timeout":"4","x":530,"y":3340,"wires":[["59d85b9286b4237c"]]},{"id":"59d85b9286b4237c","type":"debug","z":"b9860b4b9de8c8da","name":"debug 323","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":690,"y":3340,"wires":[]},{"id":"ed8a158fd90c551c","type":"debug","z":"b9860b4b9de8c8da","name":"debug 324","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":310,"y":3220,"wires":[]},{"id":"72517b3dadec43f9","type":"link in","z":"b9860b4b9de8c8da","name":"link in 2","links":[],"x":295,"y":3260,"wires":[["2c94a22c.91012e","ed8a158fd90c551c"]]},{"id":"2c94a22c.91012e","type":"function","z":"b9860b4b9de8c8da","name":"Throw Error","func":"if (msg._linkSource[0].node === \"a957d4a801015562\"){\n    node.error(\"an example error\", msg);   \n}else{\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":404,"y":3255,"wires":[["ea01375bb63004ca"]]},{"id":"ea01375bb63004ca","type":"link out","z":"b9860b4b9de8c8da","name":"link out 79","mode":"return","links":[],"x":525,"y":3260,"wires":[]},{"id":"2bd6810d.e22ece","type":"catch","z":"b9860b4b9de8c8da","name":"","scope":["a957d4a801015562","2c94a22c.91012e","bdac6f397f10a48c","1bb158698ba06402"],"uncaught":false,"x":370,"y":3520,"wires":[["2d1dcd963f2028ea"]]},{"id":"2d1dcd963f2028ea","type":"join","z":"b9860b4b9de8c8da","name":"","mode":"custom","build":"object","property":"error","propertyType":"msg","key":"error.source.name","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":530,"y":3520,"wires":[["495237ede246b15d"]]},{"id":"495237ede246b15d","type":"debug","z":"b9860b4b9de8c8da","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":670,"y":3520,"wires":[]}]

The shortcoming of a clean error handling via catch nodes as you described is the reason why I still use subflows a lot, where link calls would have been the better choice in most cases.

I ended up with the same workaround by checking the error property after the call. But that's a lot of boiler plate, that could be solved by proper error handling or error forwarding in the call node.

The catch node inside the called flow would still be necessary, of course, but the call node should rethrow all received errors so they can be properly caught via catch nodes.

That would be a nice enhancement indeed. :nerd_face:

Not a bad idea. Not sure on implementation under the hood. Would you expect any msg returned to the link-call with .error to be thrown by the link-call when it encounters it in the return sequence? What if the msg.error was deliberately added by a user node for logging/other purposes? Perhaps the catch node needs to be "subroutine aware" and set something in the embedded linkcall properties of the msg? Then there is nested link-calls :thinking:

I would personally prefer a 2nd output on the link-call for redirecting errors - but to implement that now would be a breaking change (so would need to be optional) - hey ho.

As an aside, coming in V3.1.0 is the ability to catch all errors in group. What that means is your subroutine nodes (the nodes between link-in and link-return) could be grouped and a catch inside the same group can be used to catch all errors in the group and give you the opportunity to easily re-direct the msg back to the link-return.

trying setting a complete attribute on a message while using join node - it's also a "special" flag. _linksource is a "special" attribute for link-out ... there are a number "hidden" or "special" msg attributes that are used by various nodes. Why not then also something like _error or ___error or whatever ...

_linksource is the property that is set by the link call node

Using the .error property as indicator is the only way right now. The link return doesn't (and shouldn't) know anything about the nodes connected, that would make it much more complex. I think it should only react on the message.

I think of .error as a convention for errors, just like payload for data.
I actually use it that way sometimes to generate an error that is not from a catch node, so I can use the same error handling flow path.

In some of my own nodes (request-response paradigm) I use the presence of .error to send an error reply instead of a regular data reply.
So at least for me, this convention has become a viable best practice.

Of course, using the upcoming group catch feature would reduce the effort of selection the individual nodes significantly. :+1:

I can do that today using a catch with selected nodes but as described, that does not work since the error can not be pushed out to the link call.

I'm not at computer right now :wink:

No, you need to do it all manually, redirecting MSG's with .error. (as I'm sure you know)

Essentially giving the msg a free ride to the return node in each of your subroutines then on the last link call, another redirection if .error exists

Using a second output to pass on errors wouldn't really enable usage a catch nodes on the link call.

Is rethrowing error messages by link call really a breaking change? There is no error handling at this point. Existing flows would not change, besides that the error is catchable now... :thinking:

I think the simplest solution would be if the link-call node would check for a .error and simply throw an error if found. This behaviour could be enabled with an extra flag on the link-call node: "re-throw errors should they happen" which is off by default so that backward compatibility is assured.

Then in the flows called, the catch node would pass their msg to the link-out node (as shown above in the first screenshot).

1 Like

Just thinking. What about a separate node like "link error return" to terminate the call on the error path explicitly?
Just like the special status output in subflows....

Not at all a trivial task to get right :nerd_face:

breaking is a bit strong. different is more accurate.

Imagine you had an existing flow, that catches and returns the msg with .error & your flow expected the msg to continue on its merry path (with .error in toe) - now its being thrown by the link-call.

PS, I'm not saying that is wrong - its a solid design pattern. Just different behaviour.

If you set the catch node (outside the links) to `Catch errors from (in the same group)' and delete msg.error after each link node, you will catch the errors from each of the links. Here ia an example

[{"id":"2bd6810d.e22ece","type":"catch","z":"d56a7e71249b3b10","name":"","scope":["2c94a22c.91012e"],"uncaught":false,"x":290,"y":220,"wires":[["ea01375bb63004ca"]]},{"id":"2c94a22c.91012e","type":"function","z":"d56a7e71249b3b10","name":"Throw Error 1","func":"node.error(\"an example error\", msg);   ","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":140,"wires":[["ea01375bb63004ca"]]},{"id":"72517b3dadec43f9","type":"link in","z":"d56a7e71249b3b10","name":"link in 1","links":[],"x":140,"y":140,"wires":[["2c94a22c.91012e"]],"l":true},{"id":"ea01375bb63004ca","type":"link out","z":"d56a7e71249b3b10","name":"link out 79","mode":"return","links":[],"x":535,"y":140,"wires":[]},{"id":"a957d4a801015562","type":"link call","z":"d56a7e71249b3b10","name":"to link in 1","links":["72517b3dadec43f9"],"linkType":"static","timeout":"4","x":330,"y":360,"wires":[["3bf47340bf48a32c"]]},{"id":"a1324180ccb5429d","type":"inject","z":"d56a7e71249b3b10","name":"Trigger error","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":360,"wires":[["a957d4a801015562"]]},{"id":"eee84a44f3b6bb69","type":"catch","z":"d56a7e71249b3b10","name":"Catch ALL","scope":"group","uncaught":true,"x":380,"y":560,"wires":[["1d0da1cc549ad8f3"]]},{"id":"1d0da1cc549ad8f3","type":"debug","z":"d56a7e71249b3b10","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":610,"y":560,"wires":[]},{"id":"495237ede246b15d","type":"debug","z":"d56a7e71249b3b10","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":930,"y":460,"wires":[]},{"id":"f303e4920a752c2c","type":"function","z":"d56a7e71249b3b10","name":"detect error","func":"if ( msg.error ) {\n    node.error(\"error detected\", msg)\n} else {\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":360,"wires":[["fe317d63017082da","6182bc00f1efeb67"]]},{"id":"f4758ed70b1556c6","type":"catch","z":"d56a7e71249b3b10","name":"","scope":["7d3bee7ef0b1f815"],"uncaught":false,"x":830,"y":220,"wires":[["64ce87080bda3ae3"]]},{"id":"7d3bee7ef0b1f815","type":"function","z":"d56a7e71249b3b10","name":"Throw Error 2","func":"node.error(\"an example error\", msg);   ","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":880,"y":140,"wires":[["64ce87080bda3ae3"]]},{"id":"314dd09def7c10e7","type":"link in","z":"d56a7e71249b3b10","name":"link in 2","links":[],"x":680,"y":140,"wires":[["7d3bee7ef0b1f815"]],"l":true},{"id":"64ce87080bda3ae3","type":"link out","z":"d56a7e71249b3b10","name":"link out 80","mode":"return","links":[],"x":1075,"y":140,"wires":[]},{"id":"fe317d63017082da","type":"link call","z":"d56a7e71249b3b10","name":"to link in 2","links":["314dd09def7c10e7"],"linkType":"static","timeout":"4","x":330,"y":460,"wires":[["3829ed087cc0117b"]]},{"id":"56c4f17f9e42438a","type":"function","z":"d56a7e71249b3b10","name":"detect error","func":"if ( msg.error ) {\n    node.error(\"error detected\", msg)\n} else {\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":460,"wires":[["495237ede246b15d"]]},{"id":"6182bc00f1efeb67","type":"debug","z":"d56a7e71249b3b10","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":930,"y":360,"wires":[]},{"id":"3bf47340bf48a32c","type":"change","z":"d56a7e71249b3b10","name":"","rules":[{"t":"delete","p":"error","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":360,"wires":[["f303e4920a752c2c"]]},{"id":"3829ed087cc0117b","type":"change","z":"d56a7e71249b3b10","name":"","rules":[{"t":"delete","p":"error","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":460,"wires":[["56c4f17f9e42438a"]]}]

Right, there are some edge cases to consider.

Important is, it's a solid solution where we can use the proper catch node paradigm. Not some message routing via second output, as I can't see any improvement over the current state there.

If that's something to consider as breaking change for the next major release, that'd be fine. :sunglasses:

That's not what I want, this is the flow that I would like to have:

[{"id":"2bd6810d.e22ece","type":"catch","z":"c51dd46dd5ac0f97","name":"","scope":["2c94a22c.91012e"],"uncaught":false,"x":762,"y":434,"wires":[["ea01375bb63004ca"]]},{"id":"2c94a22c.91012e","type":"function","z":"c51dd46dd5ac0f97","name":"Throw Error 1","func":"node.error(\"an example error\", msg);   ","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":812,"y":354,"wires":[["ea01375bb63004ca"]]},{"id":"72517b3dadec43f9","type":"link in","z":"c51dd46dd5ac0f97","name":"link in 1","links":[],"x":612,"y":354,"wires":[["2c94a22c.91012e"]],"l":true},{"id":"ea01375bb63004ca","type":"link out","z":"c51dd46dd5ac0f97","name":"link out 79","mode":"return","links":[],"x":1007,"y":354,"wires":[]},{"id":"a957d4a801015562","type":"link call","z":"c51dd46dd5ac0f97","name":"to link in 1","links":["72517b3dadec43f9"],"linkType":"static","timeout":"4","x":802,"y":574,"wires":[["3bf47340bf48a32c","f303e4920a752c2c"]]},{"id":"a1324180ccb5429d","type":"inject","z":"c51dd46dd5ac0f97","name":"Trigger error","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":622,"y":574,"wires":[["a957d4a801015562"]]},{"id":"eee84a44f3b6bb69","type":"catch","z":"c51dd46dd5ac0f97","name":"Catch: detect error","scope":["f303e4920a752c2c","56c4f17f9e42438a"],"uncaught":false,"x":882,"y":774,"wires":[["1d0da1cc549ad8f3"]]},{"id":"1d0da1cc549ad8f3","type":"debug","z":"c51dd46dd5ac0f97","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1082,"y":774,"wires":[]},{"id":"495237ede246b15d","type":"debug","z":"c51dd46dd5ac0f97","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1402,"y":674,"wires":[]},{"id":"f303e4920a752c2c","type":"function","z":"c51dd46dd5ac0f97","name":"detect error","func":"if ( msg.error ) {\n    node.error(\"error detected\", msg)\n} else {\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1182,"y":574,"wires":[["fe317d63017082da","6182bc00f1efeb67"]]},{"id":"f4758ed70b1556c6","type":"catch","z":"c51dd46dd5ac0f97","name":"","scope":["7d3bee7ef0b1f815"],"uncaught":false,"x":1302,"y":434,"wires":[["64ce87080bda3ae3"]]},{"id":"7d3bee7ef0b1f815","type":"function","z":"c51dd46dd5ac0f97","name":"Throw Error 2","func":"node.error(\"an example error\", msg);   ","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1352,"y":354,"wires":[["64ce87080bda3ae3"]]},{"id":"314dd09def7c10e7","type":"link in","z":"c51dd46dd5ac0f97","name":"link in 2","links":[],"x":1152,"y":354,"wires":[["7d3bee7ef0b1f815"]],"l":true},{"id":"64ce87080bda3ae3","type":"link out","z":"c51dd46dd5ac0f97","name":"link out 80","mode":"return","links":[],"x":1547,"y":354,"wires":[]},{"id":"fe317d63017082da","type":"link call","z":"c51dd46dd5ac0f97","name":"to link in 2","links":["314dd09def7c10e7"],"linkType":"static","timeout":"4","x":802,"y":674,"wires":[["3829ed087cc0117b","56c4f17f9e42438a"]]},{"id":"56c4f17f9e42438a","type":"function","z":"c51dd46dd5ac0f97","name":"detect error","func":"if ( msg.error ) {\n    node.error(\"error detected\", msg)\n} else {\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1182,"y":674,"wires":[["495237ede246b15d"]]},{"id":"6182bc00f1efeb67","type":"debug","z":"c51dd46dd5ac0f97","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1402,"y":574,"wires":[]},{"id":"3bf47340bf48a32c","type":"change","z":"c51dd46dd5ac0f97","d":true,"name":"","rules":[{"t":"delete","p":"error","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":992,"y":542,"wires":[["f303e4920a752c2c"]]},{"id":"3829ed087cc0117b","type":"change","z":"c51dd46dd5ac0f97","d":true,"name":"","rules":[{"t":"delete","p":"error","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":992,"y":701,"wires":[["56c4f17f9e42438a"]]}]

The goal is that there is an notification (i.e. send email) node at the bottom connect to the catch: detect error node and that sends me an email "link in node 2 failed because it had an underlying error" instead the email is "link in node 2 call timedout out" or if the other link-call fails first: "link in node 1 failed because a big bad monster came along" should be the message instead "link in node 1 link-call node timedout" is the message.

If I were to delete the .error then I should be sent to an institute to check my sanity since that would defeat my purpose. I want the error to be detected and the flow stop ASAP, that's the goal :slight_smile:

An extra flag on the link-out node: "capture all errors and pass them out" would replace the need for an extra catch node. The icon for the link-out node could include a baseball glove to indicate the catch-all'ness of the node! :wink:

1 Like