Tutorials/Power Automate/From Breaking to Resilient: Three Error-Handling Strategies in Power Automate
Power Automateintermediate

From Breaking to Resilient: Three Error-Handling Strategies in Power Automate

Build flows that gracefully handle failures and automatically notify you with run details.

NA
Narmer Abader
@narmer · Published June 3, 2026

No automated workflow is invincible. A broken API call, a missing column in SharePoint, or a simple division by zero can derail a critical approval process. Without proper error handling, you might never know something went wrong — until someone complains.

You can design your flows to detect failures early, alter the final run status, and provide instant access to the failing run details. These three reusable patterns will make your solutions more reliable and transparent.


Pattern 1: The Three-Act Error Handler (Try, Catch, Finally)

This first pattern mirrors the classic try‑catch‑finally structure found in programming languages. You have three clearly separated actions or groups of actions:

  • Try – Execute the operation that might fail.
  • Catch – Run an action only if the Try step fails.
  • Finally – Perform an action regardless of whether the Try succeeded or failed.

Step‑by‑step implementation

  1. Set up a starting flag Before the Try action, initialize a boolean variable called varFailureFlag and set its default value to false. This flag will later tell your flow whether an error occurred.

  2. Create the Try action Add a Compose action and name it ForceError. Use an expression that deliberately fails:

    textForced failure – division by zero
    div(1,0)

    When this action runs, it will throw an error because you cannot divide by zero.

  3. Build the Catch action Add a Set variable action called SetFailureFlag. Choose varFailureFlag and set it to true.

    Open the Configure run after settings (in the new designer: click the action, then “—” overflow → “Configure run after”; in the classic designer: three dots on the action title bar) and uncheck every box except “has failed”.

    This makes the Catch action fire only when ForceError fails.

  4. Create the Finally action Add a Send an email (V2) action to notify you that the flow completed.

    In its Configure run after settings, check all four boxes: “is successful”, “has failed”, “is skipped”, and “has timed out”.

    The email will be sent whatever happens.

Test the three‑act pattern

Run the flow. The Compose action will fail, the SetFailureFlag action will execute, and you will still receive the final email.

Note: The flow run will probably show “Succeeded” because the last action (the email) succeeded. Pattern 2 fixes this.

Modern approach: Scope containers

In the new Power Automate designer (default since 2023), wrap your Try actions inside a Scope container and set the Catch scope’s run-after to “has failed” on the Try scope. This eliminates the flag variable and gives you the same visual Try‒Catch structure. Inside the Catch scope, the expression actions('TryScope')?['error']?['message'] surfaces the error message directly, without a separate variable.


Pattern 2: Signaling the True Run Status

The first pattern doesn’t change the run’s final status. If the last action succeeds, Power Automate reports the whole run as successful — even though the Try step failed. We want the run to appear Failed when an error occurs.

Modifying the flow

  1. Remove the final email from the Finally section.

  2. Add a Condition action. Configure its run‑after to all four boxes (the same way you did for the Finally email).

  3. In the Condition, check whether varFailureFlag is equal to true.

    textCondition rule
    @equals(variables('varFailureFlag'), true)
  4. If yes (failure path)

    • Send a “Flow failed” email.
    • Add a Terminate action, set its Status to Failed, and provide a clear reason.
    textTerminate reason
    The flow encountered an error in the Try step.
  5. If no (success path)

    • Send a “Flow succeeded” email.
    • Add another Terminate action, set its Status to Succeeded.

Now the run’s status will accurately reflect whether an error happened.

Test the updated flow

Run the flow again. This time, after the forced error, the run will show Failed in the portal, and you will receive the appropriate email.


Knowing that a flow failed is not enough. You need to inspect why it failed. Hunting through a long list of runs wastes time. Instead, embed a clickable link to the exact run inside your failure email.

Retrieving run metadata

Add two Compose actions inside the If yes (failure) branch:

  1. GetRunInfo – expression:

    textGet workflow metadata
    workflow()

    This returns an object containing the environment GUID, the flow GUID, and the current run’s GUID.

  2. BuildRunLink – expression that assembles the run URL:

    textConstruct the deep link
    concat('https://make.powerautomate.com/environments/', outputs('GetRunInfo')?['tags']?['environmentName'], '/flows/', outputs('GetRunInfo')?['name'], '/runs/', outputs('GetRunInfo')?['run']?['name'])

In the email action located in the failure branch, switch the body to HTML format. Insert a hyperlink using the dynamic content token from BuildRunLink:

htmlEmail body with clickable run link
<a href="@{outputs('BuildRunLink')}">Click here</a> to review the flow run details.

When the email recipient clicks the link, they are taken directly to the run details page, where they can see which action failed and the error message.

Tip: The workflow() function is available in both classic and child flows. In solution‑aware flows the property names remain the same.


Common Pitfalls to Avoid

  • Wrong run‑after configuration – For Catch actions, uncheck everything except “has failed”. For Finally actions, check all four options (including “has timed out”) so the action always runs.
  • Using Initialize instead of Set Variable – Initialize creates a new variable only if the action runs, and it cannot change an existing value. Use Set Variable to update a pre‑initialised flag.
  • Forgetting to set the Terminate status – Without Terminate, the run status depends on the last action, not on your intended outcome.
  • Malformed URL – Double‑check the property names (tags.environmentName, name, run.name) by temporarily saving the output of workflow() into a file. The environmentName is a unique GUID, not a friendly name.
  • Missing permissions – The person who receives the email must have at least read access to the flow’s environment to open the run link.

Performance, Security, and Delegation Notes

  • The workflow() expression is lightweight and runs once per run; it does not affect throttling limits.
  • The run URL contains only resource identifiers, not secrets. Still, only send the email to trusted recipients.
  • The patterns shown work in any trigger type; no delegation concerns arise because they use built‑in functions only.

Final Recommendation

Apply these three patterns to every production flow that processes business‑critical data. The overhead is minimal (a variable, a few Compose actions, and run‑after configuration), but the benefits are huge:

  • Immediate awareness when a flow fails.
  • Accurate run history that matches real outcomes.
  • Fast troubleshooting with a deep link to the exact failure point.

Start with the Try‑Catch‑Finally skeleton, add the Terminate logic to fix the run status, and finish with the deep link to make investigation painless. Your future self—and your users—will thank you.


References