Catch errors

When a workflow throws an error during execution, it can be caught and handled.

Note: There is a known issue where the placement offor directly aftertrycauses an error. For details and the workaround, seeKnown issues.

Use atry/except structure

You can use atry/except structure for error handling. For example:

YAML

-STEP_NAME:try:call:http.get...except:as:ERROR_MAPsteps:...

JSON

[{"STEP_NAME":{"try":{"call":"http.get"...},"except":{"as":"ERROR_MAP","steps":...}}}]

ReplaceERROR_MAP with the name of a map variable thatcontains the error message.

For example, the map for anHttpError error (with an HTTP status code >=400)has the following attributes:

  • tags:HttpError string
  • message: human-readable error message
  • code: HTTP status code
  • headers: response headers
  • body: response body

For other error tags, seeWorkflow errors.

Note that thesteps block is optional. It can contain the following:

Variable scope

A variable created inside anexcept block belongs to thelocal scope of thatblock, and is accessible only in that scope. For details, seeVariables.

If you are assigning a variable inside anexcept block and want to access thevariable outside of the block, assign the variablebefore the block to placeit in the surrounding scope. For details, seeShare a variable before anexcept block.

Example oftry/except structure

For example, Workflows considers any HTTP request that returnsstatus code400 or greater failed. This makes the workflow execution failunless the workflow catches and handles the error:

YAML

-read_item:try:call:http.getargs:url:https://host.com/apiresult:api_responseexcept:as:esteps:-known_errors:switch:-condition:${not("HttpError" in e.tags)}return:"Connectionproblem."-condition:${e.code == 404}return:"Sorry,URLwasn'tfound."-condition:${e.code == 403}return:"Authenticationerror."-unhandled_exception:raise:${e}-url_found:return:${api_response.body}

JSON

[{"read_item":{"try":{"call":"http.get","args":{"url":"https://host.com/api"},"result":"api_response"},"except":{"as":"e","steps":[{"known_errors":{"switch":[{"condition":"${not(\"HttpError\" in e.tags)}","return":"Connection problem."},{"condition":"${e.code == 404}","return":"Sorry, URL wasn't found."},{"condition":"${e.code == 403}","return":"Authentication error."}]}},{"unhandled_exception":{"raise":"${e}"}}]}}},{"url_found":{"return":"${api_response.body}"}}]

Thetry block can contain multiple steps, allowing them to share the sameexcept block for error handling:

YAML

-read_item:try:steps:-step_a:call:http.getargs:url:https://host.com/apiresult:api_response1-step_b:call:http.getargs:url:https://host.com/api2result:api_response2...except:as:esteps:-KnownErrors:...

JSON

[{"read_item":{"try":{"steps":[{"step_a":{"call":"http.get","args":{"url":"https://host.com/api"},"result":"api_response1"}},{"step_b":{"call":"http.get","args":{"url":"https://host.com/api2"},"result":"api_response2"...}}]},"except":{"as":"e","steps":[{"KnownErrors":null}...]}}}]

Use atry/retry/except structure

You can also use atry/retry/except structure for error handling. For example:

YAML

-step_name:try:steps:-step_a:call:http.getargs:url:https://httpstat.us/404retry:${http.default_retry_non_idempotent}except:as:esteps:-checkForTimeout:switch:-condition:${e.code == 404}return:"notfound_404"-condition:${e.code == 408}return:"timeout_408"-raiseError:raise:${e}-returnSuccess:return:"Success"

JSON

[{"step_name":{"try":{"steps":[{"step_a":{"call":"http.get","args":{"url":"https://httpstat.us/404"}}}]},"retry":"${http.default_retry_non_idempotent}","except":{"as":"e","steps":[{"checkForTimeout":{"switch":[{"condition":"${e.code == 404}","return":"notfound_404"},{"condition":"${e.code == 408}","return":"timeout_408"}]}},{"raiseError":{"raise":"${e}"}}]}}},{"returnSuccess":{"return":"Success"}}]

For more information, seeRetry steps.

Catch and handle HTTP request errors

This sample implements a custom exception handler based on the HTTP status codereturned by the GET request. The workflow catches a potential exception andreturns a predefined error message. If an exception is not recognized, theworkflow execution fails and throws the exception as returned by the GETrequest.

The same pattern could be used to catch exceptions raised byCloud Run or Cloud Run functions workloads.

YAML

# Use a custom exception handler to catch exceptions and return predefined# error messages; if the exception isn't recognized, the workflow# execution fails and throws the exception returned by the GET request-read_item:try:call:http.getargs:url:https://example.com/someapiauth:type:OIDCresult:API_responseexcept:as:esteps:-known_errors:switch:-condition:${not("HttpError" in e.tags)}next:connection_problem-condition:${e.code == 404}next:url_not_found-condition:${e.code == 403}next:auth_problem-unhandled_exception:raise:${e}-url_found:return:${API_response.body}-connection_problem:return:"Connectionproblem;checkURL"-url_not_found:return:"Sorry,URLwasn'tfound"-auth_problem:return:"Authenticationerror"

JSON

[{"read_item":{"try":{"call":"http.get","args":{"url":"https://example.com/someapi","auth":{"type":"OIDC"}},"result":"API_response"},"except":{"as":"e","steps":[{"known_errors":{"switch":[{"condition":"${not(\"HttpError\" in e.tags)}","next":"connection_problem"},{"condition":"${e.code == 404}","next":"url_not_found"},{"condition":"${e.code == 403}","next":"auth_problem"}]}},{"unhandled_exception":{"raise":"${e}"}}]}}},{"url_found":{"return":"${API_response.body}"}},{"connection_problem":{"return":"Connection problem; check URL"}},{"url_not_found":{"return":"Sorry, URL wasn't found"}},{"auth_problem":{"return":"Authentication error"}}]

What's next

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2026-02-19 UTC.