States can encounter runtime errors for various reasons:

  • Transient errors, such as network outages and congestion
  • JSON path resolution errors

By default, when a state encounters a runtime error, the entire ZIS flow fails.

Action and Map states support error handling using Catch and Retry blocks. You can use these blocks to avoid failing the entire ZIS flow when a state encounters an error. See Using a Retry block and Using a Catch block.

In certain situations, ZIS also attempts to retry failed flows. See ZIS flow retry logic.

Using a Retry block

You can use a Retry block to define a retry policy for an Action or Map state that encounters a runtime error. The policy lets you retry the state a specific number of times. You can also increase intervals between retries.

For example, the following Retry block makes up to two retry attempts. After the first runtime error, the state waits for three seconds to retry. If the retry encounters an error, the state waits for six seconds to retry again. If the second retry fails, the entire ZIS flow fails.

"Zendesk.GetTickets": {  "Type": "Action",  "ActionName": "zis:INTEGRATION:action:zendesk.get_tickets",  "Parameters": {    "accessToken.$": "$.connections.zendesk.access_token"  },  "Retry": [    {      "ErrorEquals": ["States.ALL"],      "IntervalSeconds": 3,      "BackoffRate": 2.0,      "MaxAttempts": 2    }  ],  "Next": "NextState"}

Supported properties for a Retry block

Objects in the Retry array support the following properties.

Name Type Mandatory Description
ErrorEquals array of strings true Array of error names. Only valid value is "States.ALL", which matches all error names
IntervalSeconds number false Number of seconds the state waits before attempting the first retry. Must be a positive, non-zero integer
BackoffRate number false Multiplier used to increase the IntervalSeconds retry interval on subsequent retries. Must be a positive, double-precision floating-point number. Defaults to "2.0"
MaxAttempts number false Maximum number of retry attempts. Doesn't include the first run attempt. Must be a positive integer. Defaults to "3"

Using a Catch block

A Catch block specifies a fallback state to run if an Action or Map state encounters a runtime error and can't retry. This can occur if the state has exhausted the retry attempts in its Retry block or doesn't include a Retry block. Example:

"Zendesk.GetTickets": {  "Type": "Action",  "ActionName": "zis:INTEGRATION:action:zendesk.get_tickets",  "Parameters": {    "accessToken.$": "$.connections.zendesk.access_token"  },  "Retry": [    {      "ErrorEquals": ["States.ALL"],      "IntervalSeconds": 3,      "BackoffRate": 2.0,      "MaxAttempts": 2    }  ],  "Catch": [    {      "ErrorEquals": ["States.ALL"],      "Next": "AnotherState"    }  ],  "Next": "NextState"}

Supported properties for a Catch block

Objects in the Catch array support the following properties.

Name Type Mandatory Description
ErrorEquals array of strings true Array of error names. Only valid value is "States.ALL", which matches all error names
Next number true Fallback state to run if the Action or Map state encounters a runtime error and can't retry
ResultPath number false JSON reference path used to the store the state's output. Later states of the ZIS flow can access the output at this path. Defaults to "$", which replaces the state's input with its output

ZIS flow retry logic

A running ZIS flow will retry if it:

During a retry, the entire flow will run again from the beginning. Ensure your use case and flow logic accounts for this.

The interval between retries varies based on the retry scenario. Regardless, ZIS will only attempt to run a flow three times: the initial attempt and up to two retry attempts.

Retrying a ZIS flow on a fail state

If a flow ends on a fail state, ZIS will retry the flow after 30 seconds, then again after a further 60 seconds.

Retrying a ZIS flow after rate limiting

A 429 HTTP status code means "too many requests." When an API returns an error with this code, it means an account is sending too many requests to the API too quickly. This is called rate limiting.

Some APIs include a Retry-After header in responses with a 429 error. This header specifies a period of time you should wait before retrying the API call.

If an HTTP-based action in a flow receives a 429 error and the flow fails, the flow will retry based on the Retry-After header's value.

Retry-After header value Flow Retry behavior
Less than 120s (120 seconds) Retry after the Retry-After interval
120s or greater Retry after 120 seconds
No Retry-After header Retry after 30 seconds, then again after a further 60 seconds

Retrying a ZIS flow after a server error

A 500 HTTP status code means something has gone wrong with the API's web server.

If an HTTP-based action in a flow receives a 500 error and the flow fails, the flow will retry after 30 seconds, then again after a further 60 seconds.

Manually retrying a ZIS flow

To manually retry a flow for other types of errors, use a Catch block in an Action state to catch the error, followed by a Choice state to check for a specific error code. Example:

{  "StartAt": "Zendesk.GetTicket",  "States": {    "Zendesk.DoSomething": {      "Type": "Action",      "ActionName": "zis:YOUR_INTEGRATION_NAME:action:zendesk.YOUR_ACTION_NAME",      "Parameters": {        "ticketId.$": "{{$.input.ticket.id}}",        "accessToken.$": "$.connections.YOUR_TARGET_SYSTEM.access_token"      },      "Catch": [        {          "Comment": "ZIS only supports catching all error types, i.e. States.ALL",          "ErrorEquals": [            "States.ALL"          ],          "Next": "CheckErrorType"        }      ],      "ResultPath": "$.do_something_result",      "End": true    },    "CheckErrorType": {      "Comment": "Checks whether the error caught is a 404",      "Type": "Choice",      "Choices": [        {          "Variable": "$.Cause",          "StringEquals": "external action failed due to status code: 404",          "Next": "log.errorCaught.404"        }      ],      "Default": "log.errorCaught.other"    },    "log.errorCaught.404": {      "Comment": "Use this branch to handle 404 error",      "Type": "Succeed",      "Message": "I caught a 404 error"    },    "log.errorCaught.other": {      "Comment": "Use this branch to handle other errors",      "Type": "Succeed",      "Message": "I caught a non-404 error"    }  }}