How to handle errors in Frends Processes

Collection of methods to properly handle errors in Processes.

Because errors happen in integrations and in computing in general, it is a good idea to prepare for them. Whenever there's systems and data not directly controllable by the developer, there's a chance an unexpected, or even expected error might occur.

Whenever a Task or shape causes exception to be thrown from it, unless there's handling set up for catching the exception, the Process execution will be interrupted. As this is not always wanted, Frends contains features that help in handling these.

Here's a collection of guides and tips on how to handle errors and exceptions that might occur in Frends Processes.

Handling errors from a single Task

Tasks are used for most everything, from reading and writing files to connecting to an external API and databases. It's thus more than likely that some errors are bound to occur when executing Tasks.

Retry on failure

Sometimes some errors occur only occassionally, and trying again a bit later fixes the issue. These are common errors when connecting to external systems, where anything from the connection to the target system might be experiencing issues.

Tasks include a parameter called Retry on failure, available under Advanced settings in the Task parameters. This parameter allows repeating the Task's action if the attempt results in the Task throwing an exception.

Retry option in Task parameters.

A Task can be automatically retried up to 10 times. Setting the value to 1 (one) means that if a failure occurs, it will try again once.

The retries are done using an exponential backoff wait time. The formula for the exponential backoff wait time is 500 ms * 2 ^ (retry count).

Retry attempt    Wait time (seconds)
1 try            1 second
2 try            2 seconds
3 try            4 seconds
4 try            8 seconds
5 try            16 seconds
6 try            32 seconds
7 try            64 seconds
8 try            128 seconds
9 try            256 seconds
10 try           512 seconds

HTTP Request example

When using HTTP Request Task, it is common to set Retry on failure option because connections over the internet can be prone to errors.

Process with HTTP Request Task with Retry enabled.

Retry on failure will attempt to run the Task again, if the Task ends up in an exception. By default, if the HTTP connection does not succeed due to timeout or unable to set up SSL for HTTPS connection, this will result in an exception.

However, if the connection succeeds but the resulting HTTP status code indicates error, such as 404 page not found or 500 internal server error. This does not automatically create an exception in the Process, because the response was obtained and the connection technically worked.

HTTP Request Task contains a parameter for Throw exception on error response, which can be used to trigger the Retry on failure on erroneus responses as well, and ultimately interrupting the Process flow if the status code indicates an error.

Using these options together may be beneficial for your use case, if you absolutely need the HTTP Request to succeed in order to continue with the Process.

Catch shape

Catch shape, with or without using a Scope, can be used to handle uncaught exceptions from Tasks, without interrupting the Process flow immediately. Using Catch shape is useful if you want to try to continue the Process flow with some error checking or other additional logic instead of simply retrying without changes.

It might also be necessary to prepare for the situation where retry was attempted but it didn't succeed, so some clean up actions and reporting might be necessary before ending the Process execution into failure.

You can read more about how to use Catch shape from it's reference documentation.

Catching directly from a Task

While slightly more uncommon setup, connecting Catch shape directly to a Task is possible and creates for a slightly more compact Process flow than when using a Scope. Read after this chapter to learn more about how to combine usage of Catch and Scope for more powerful error handling.

Catching exceptions directly from a Task requires some setup.

In order to catch the exceptions directly from a Task, you need to prepare a variable to store a state or result value from a Task. This can be anything from a numerical value representing the HTTP status code, to a new object that the result can be assigned into.

If the Task is successful the Process execution will not execute the Catch shape's path, but instead continues directly to the Exclusive Decision. There we can check whether the HttpResult variable contains an error value, and continue the Process if not. The HttpResult variable in this case will continue holding the initial value it was set to.

Successful execution path for the Process highlighted in green.

If the Task threw an exception, Catch shape and its Assign Variable shape will be executed instead. Assign Variable is used here to set the HttpResult variable's value to some other value, that will represent an error. The Exclusive Decision shape will notice this, and direct the Process execution towards error handling path.

Execution path for when Task throws an exception.

Note that without Scopes, there can be only one shape after Catch shape, before the execution path merges with the successful execution path. There can also be no shapes after the Task we are catching from before merging the path from the Catch shape.

The #result reference value from the Task shape also cannot be used in the error handling here, nor in the Exclusive Decision. It is only safe to use after the Exclusive Decision, when it has been deemed to have been successful.

This error handling scenario will also not provide further information about why the Task threw an exception, unless the error variable's value is stored in the Catch shape's path. This is the largest flaw of this error handling method.

Catching with Scopes

Catching from and to a Scope shape enables handling errors in the most flexible way possible, and it can be used to handle errors from more than one Task or Shape at once.

Skip over to the next chapter to learn more about handling errors with Catch and Scope shapes for a part of Process at a time to learn more about this method.

For using the method for a single Task, simply include the Task in a Scope of its own, and attach the Catch shape and corresponding Scope shape for error handling to perform it for a single Task alone.

Exceptions in Code Tasks

Exceptions might happen in Code Tasks as well, if there unexpectedly are missing values or values are in different format than expected.

Validation and sanitation

Before handling values obtained from elsewhere, it is a good idea to validate and check that the values are there and what you expected. This allows handling them properly later on in your code, generating less errors. Sanitating user input is also generally a good idea to avoid security issues.

Try and catch

Like with Tasks in Processes and in general programming, try and catch pattern can be used in Code Tasks as well. This allows for executing code that might fail due to possibly unknown data received from an external source, without interrupting the Process flow.

Try and catch in Code Task follows the standard C# programming.

{
    var input = #result[HTTP Request].Body;
    JObject obj;

    try {
        // Try convert HTTP result into a JSON Object
        obj = JObject.Parse(input);
    } catch (Exception e) {
        // Return error JSON object
        return JObject.FromObject(new {
            Error = "Invalid response"
        });
    }

    // Return converted HTTP results
    return obj;
}

Handling errors within a Process

The most common method to handle errors within Process is to use two Scope shapes and a Catch shape to perform a try-catch pattern in Processes.

Scopes & Catch shape

In order to handle errors from a part of a Process, surround the part with a Scope shape. Then connect a Catch shape to the Scope, and further connect another Scope shape after the Catch to perform the error handling in.

Standard error handling model within Processes.

Catch shape has very specific requirements when it comes to connecting it to Processes, unlike most other shapes.

The error handling must be done within one shape after the Catch shape. If more than one shape is required, using Scope shape as the error handling shape allows you to perform more complex logic. Scope shape as the error handler is the most common setup for catching and handling errors.

The error handling path must also join back to the main Process flow right after the shape you are catching errors from. There can be no shapes in between.

Example of Catch shape performing error handling in a Process.
If error occurs within the Scope, Catch shape will catch the error and handle it in alternative branch.

Error handling within loops

The order of shapes in your Process matter when you are creating error handling for loops, such as Foreach or While shapes.

Stop iteration if exception is thrown

In order to stop iteration if an exception is thrown, but you want to catch the exception and handle it using a Catch shape, surround the iteration shape with a Scope shape, and then connect the Catch shape into the Scope. When the shapes are set in this order the exception will propagate from the iteration, interrupting it, but the following Scope and Catch shapes will then catch and handle the exception.

While loop will be interrupted if an exception occurs.

This is useful strategy if the iteration's further steps expect that earlier steps succeeded and that the handled data should be complete and valid when moving forward.

Continue iteration after handling exception

If you want to continue iteration til the end and collect all results, be it successful or not, placing the iterative shape around a Scope and Catch pattern is the answer.

Including the Scope and Catch shapes within the iteration allows it to continue.

In this pattern, the shapes within an iterative shape are surrounded by a Scope shape, that has a Catch and Scope shape attached to it, also included within the iterative shape.

When an exception occurs within the iteration, the exception is caught and handled inside the iteration. Because the exception is not allowed to propagate past the Catch shape, the iteration can continue once the error is handled.

Noteworthy is that the container for error messages or other info from the error handler should be initialized before the iteration. Otherwise the error messages would not survive to be used after the iteration.

In case the error handler or iteration logic itself has an exception thrown the iteration will stop, because those exceptions are thrown outside the Scope shape. For example the underlying data changing may break the Foreach scope, or cleanup and reporting operations failing within the error handling Scope would cause the exception propagating past the iteration shape.

Handling errors for a single Process Instance

Whenever a Process ends in an error state, meaning that the Process Instance will be reported as failed, an exception has been thrown so that it was not caught by the included error handlers within the Process flow.

All exceptions were not caught within the Process, resulting in failed executions.

While it is a good idea to let Process Instances end in failed state if an error occurred for monitoring purposes, by finishing a Process instance in Throw shape instead of Return shape, you can also connect an additional error handler to the Process to be run if any exceptions remain uncaught.

Subprocess to call on unhandled error

When a Process ends with an uncaught exception, be it from the Throw shapes and planned by the developer, or from unexpected errors the developer did not prepare for, a Subprocess can be attached and executed to the Process to be executed when the Process execution fails.

While the Subprocess to call on unhandled error does not allow continuing the Process execution in any scenario, it gives a final moment and execution path to perform data cleanup and reporting for the failed Process execution. The feature is commonly used to perform error reporting by automatically creating a ticket to IT support when a Process fails.

Subprocess to call on unhandled error works in a similar way as how Call Subprocess shape.

In order to set up the Subprocess, open the Process settings and click on Select Subprocess to call on unhandled error. The Subprocess has to be created before it is selectable here.

Once selected, you can define the parameters for the Subprocess. You can read more on what values are available to use in the Process reference documentation.

Designing an error handling Subprocess

While the specifics of each error handling Subprocess vary for different use cases and situations, here are some common actions that Subprocesses can do for handling errors during and after Process executions.

Error reporting

Most common action is to report the error. This can be done by sending an email to people or to a ticketing system, giving details about what Process failed, and what the error was.

Reduce the amount of reports

While only a single Send Email Task can be used within the Subprocess to report any and all errors occuring in Processes, this can cause an excessive amount of reports for the same error, making the error reporting less effective.

Shared State Tasks can be used to create a limiter on how often a report should be sent, by saving the time stamp on when the error was last reported.

Data cleanup and repair

While more situational than the generic error reporting applicable to all Processes, cleaning up and repairing the data that didn't get processed correctly and completely is often recommended action to avoid further issues.

Retrying the Process execution

By using Triggers such as AMQP Trigger, HTTP Trigger or File Trigger in your actual Process, it's possible to execute it again by the Subprocess. Especially AMQP and other message bus Trigger types are good candidates for this by re-sending the received message into the queue, and allowing the Process to receive and attempt handling for another time.

Limiting the retries

When performing a retry for a whole Process, it's recommended to have it delayed and the number of retries limited to avoid infinite loop of Process executions that end in error.

Shared State Tasks and Sleep Task can be used for performing the retry limiting and delay, in case the retry method does not support these by itself. For example, Service Bus queues allow delayed requeueing of messages, and message properties can be set to count the number of requeues.

Handling errors based on multiple Process Instances

Not all situations in integrations can be seen as errors, if we are only focusing on monitoring and handling errors by each Process Instance alone.

For example, it might not be an error by itself if at some point there is no data to be handled for a single Process Instance, but when it happens for multiple Instances in a row, there might be something wrong in the data delivery to that Process.

You also cannot handle errors in Processes, if the error is that the Process does not get executed at all. For example for APIs this might happen, that the Processes depend on external systems and actors to execute. If the Process does not get executed, there is no errors in that Process either, but that by itself can be an error.

Monitoring Rules is the solution in Frends to these scenarios, where the error is defined by the number of Process Instances and their details together, instead of by the single Process Instances by themselves.

Using Monitoring Rules for error handling

Monitoring Rules inspect the execution of all Processes in an Environment as a whole and focuses on the data being processed instead of the technical success of the Processes.

This means that instead of trying to figure out if a Process has been successful in for example delivering orders to their destination inside a single Process, you can gather up all the orders from a set period of time and see if enough have been delivered. ​ You create rules to check for given Promoted Values in the database during a time interval, e.g. if the count of "OrderId" values ever goes under 100 within an hour, or if there are any instances of a "PROC-e234-ERROR" value being promoted.

Rules are defined for each Environment. So, in order to create a new Monitoring Rule, go to Administration > Monitoring Rules view, and choose Create new.

Alert if number of matching Process Instances is less than expected

The following configuration shows a common rule of sending an alert if not as many Process Instances have been executed than expected, that match the rule of having an OrderID Promoted Value for the Process Instance.

Rule for monitoring the number of instances.

In the example, an alert would be sent if less than 100 Process Instances were found with OrderId Promoted Value during each hour. The rule will check for all Process Instances that were executed during the hour, and count how many of them had the OrderId value. If it was less than 100, the rule triggers a Process.

Instead of triggering a Process if the alert is made, the Monitoring Rules can also send an automated email to alert thespecified recipients.

Alert if there are more matching Process Instances than allowed

If you are using Promoted values to promote that a Process Instance encountered an error, the example rule above can be reversed to trigger an alert, if more than the specified number of Instances were found within the hour.

Alert if Promoted Values match the rule

Values of the Promoted Values can also be used as a rule, not just the count of Promoted Values existing.

This rule can be used in similar fashion, with the addition of the value having to be equal, more than or less than what is set. It's also possible to trigger the rule if the sum of chosen Promoted Value, or maximum value of it, exceeds the set value.

Example of monitoring Promoted Values that are larger than 3.

Only monitor during specific time

Each Monitoring Rule also contain date and time settings to set when the rule is active. For example, you might expect orders to come in during day time, while during night it is acceptable to not have as many orders being handled.

Last updated

Was this helpful?