Automatically handle failures in tasks

By default, when a task in a release fails, the release stops so you can retry the task, skip the task, or add new tasks to resolve the issue. If the Abort on failure option is selected, the release immediately aborts if a failure occurs. This is useful for Continuous Integration/Continuous Delivery environments in which a new code commit will fix the problem and start a new release.

These options provide general support for both fully and partially automated release scenarios. In some scenarios, you may want to execute certain actions if a task fails; for example, cleaning up resources or notifying a certain team. This topic will describe two approaches:

Release has property on the task level called Handling failure. You can use this to execute a Jython script when the task fails its execution or just to skip the task. For more information, see Task failure handler.

The examples shown here are based on a sample template that you can download and import. Note: This requires adding a custom task type, which you can do by copying the type definition to the ext directory or by downloading and installing this community plugin.

Important: The code provided in the Gist is sample code that is not officially supported by If you have questions, please contact the Support team.

Handling failure in the task

The simplest and most effective way to handle failure in a task is to include the appropriate error-handling logic in the task implementation itself. For example:

Sample Jython Script task with cleanup

This approach allows you to retry the task multiple times without accumulating a backlog of items that need to be cleaned up later. Example: If a task tries to create a user and then create a ticket, you can add a failure handler around the “create ticket” part so you can delete the user if the ticket was not created successfully. Replace this section:

newUser = createUser()
ticket = createTicket(newUser)

With this logic:

newUser = createUser()
  ticket = createTicket(newUser)

You can use this approach with Remote Script tasks, Jython Script tasks, and custom tasks. Example of a Remote Script task:

Sample Remote Script task with cleanup

Handling failure in a conditional block

In cases where the task implementer does not know which actions need to be taken when a task fails, you can add a group immediately following the task with a condition that ensures that it only executes if the task does not succeed. For example:

Group that handles failure

In this case, the task must:

  • Complete its executing without triggering a task failure. A Remote Script task must exit with a non-zero exit code, and a Jython Script task must not throw an exception.
  • Set the value of a variable to an appropriate value for the conditional group to determine if it should execute. In some cases, this can occur by default Examples: There can be a standard output or error. For HTTP requests, you may want to expose the response code for this purpose.

Sample Jython Script task

This is an example of a Jython Script task that succeeds and sets a variable with the response code of the HTTP request it executes.

Sample Jython Script task that sets a variable

The associated group then checks the variable in its precondition.

Group with a precondition

If you want the release to fail after the cleanup operation is done, add a task that fails to the end of the conditional group.

Task that will cause the release to fail

Sample Remote Script Task

For Remote Script tasks, you can determine if a task succeeded by looking at the standard output or standard error, which are available as variables.

For remote tasks, you can to determine if a task did not succeed by looking at the standard out or standard error, which are already available as variables. Note: The remote script is configured to always return exit code 0, so the Release task will not fail:

Sample custom Webhook task

This approach can be used with other task types, with some customizations. Example: This sythetic.xml code extends the Webhook task type with a type that always succeeds and provides the HTTP response code as an output variable that can be used in subsequent tasks.

<type type="acme.JsonWebhook" extends="webhook.JsonWebhook">
    <property name="statusCode" kind="integer" category="output" required="false"
      description="The HTTP status code of the response" />
    <property name="alwaysSucceed" kind="boolean" category="input"
      required="false" default="false" description="If checked, this task will
        succeed irrespective of the HTTP response code. The 'statusCode' output
        property can be checked by subsequent tasks to determine whether the call
        was actually successful." />

This also requires minor changes to the implementation:

Updated implementation

You can use the modified Webhook task with a group that checks the status code to determine if the task executed successfully.

The type definition and task implementation are available as part of the Gist mentioned above.

Important: The code provided in the Gist is sample code that is not officially supported by If you have questions, please contact the Support team.