Failure handling -- SEQUENCE vs TRY/CATCH

As many already know, the long-time approach to handling failures is to use this structure:

SEQUENCE (exit on SUCCESS)
…SEQUENCE (exit on FAILURE)
…SEQUENCE (exit on DONE/FAILURE)

where the nested SEQUENCEs are basically the try and catch blocks respectively.

Version 10.3 introduced the TRY/CATCH/FINALLY steps to support a more “Java-like” exception handling mechanism. I’ll defer to the docs for the descriptions of the whys and the hows.

Thinking that TRY/CATCH would be pretty much the same as the nested SEQUENCE approach, we’ve started using TRY/CATCH. However, it appears there is a behavior that differs. The pipeline in the CATCH block is as it existed at the time of the error. This increases the chances of variable collisions (what I call “pipeline litter”). In one case, an HTTP call returned an error, for which our wrapper service throws an exception. In the top-level service that called the wrapper, there is the TRY/CATCH. Because of the thrown exception, the “loadAs” var for the HTTP call was left in the pipeline. In the CATCH block there was a call to a different HTTP endpoint to create a help desk ticket – the erroneous value for that caused the HTTP call to behave differently than expected, causing an error in later steps.

Long-story short (too late?) does someone know of a way to restrict the pipeline context in a CATCH so that it behaves similarly to the nested SEQUENCE approach? That is, only the vars that existed before the SEQUENCE block was entered would be present and if one wants to get data as it existed in the try block at the time of the exception then call getLastError to do so. Perhaps I’m missing something simple.

1 Like

Hmm. No one else has run into this? Interesting.

One obvious approach is in the CATCH/FINALLY blocks use scopes to limit the pipeline from individual steps. Requires additional mapping steps but that’s not an issue I suppose.

Interestingly, the docs seems to overstate the “problem” with nested SEQUENCES for try/catch:

However, using SEQUENCE steps in this manner may result in flow services that are hard to read, debug, and maintain. Additionally, the approach is error prone as it requires the flow service developer to replicate a design pattern repeatedly and to remember to set various properties for each flow step.

Developers that are new to FLOW learn and recognize this construct almost immediately. True, it needs to be explained first but so does the behavior of TRY/CATCH. :slight_smile: Using SEQUENCE vs TRY/CATCH is trade off of what one needs to remember to do. The TRY/CATCH/FINALLY steps definitely add capability in terms of being able to handle different exceptions in different ways more readily. Developers just need to be aware of how it behaves otherwise they can be bit by unexpected behavior if they don’t take steps to address the increased probability of pipeline variable collisions that TRY/CATCH steps have.

1 Like

Thanks for digging into that, Rob.
I saw the same behavior and was questioning the logic behind it.
I personally do not find any obfuscation to using the old tried and true method of SEQUENCES; just make sure that you comment the sequences properly and keep your pipeline clean and tidy.

It’s on my plate to dig more into this as soon as I can, as I do like the right-click add a try/catch block approach.

1 Like

The TRY/CATCH is indeed more readable and convenient. Just need to be aware of how pipeline handling differs and take steps to avoid pipeline var collisions. A tidy pipeline is indeed a good practice but in the face of an exception, all bets are off. :slight_smile: There will be vars left in place that you likely don’t want in your exception handling. Related to this, some may be tempted to use clearPipeline. Beware of that because common use of that has it’s own set of gotchas.

2 Likes