Introduction

Power Automate makes it easy to automate business processes, but building a flow is only one part of the solution.

When a flow is running in a production environment, failures are inevitable. A SharePoint action may fail, an API may return an error, an email address may be invalid, or a connector may temporarily become unavailable.

The real challenge is not only detecting that the flow failed.

The challenge is:

How do we know what failed, why it failed, which flow run was affected, and how can the support team quickly investigate it?

In this article, we will build a reusable error-handling framework using Power Automate.

The framework will capture:

It will then generate a professional HTML email notification for the support team.

What We Are Building

Our final solution will follow a Try-Catch-Finally pattern.

Trigger

TRY Scope

Business Process

Success ───────────→ Continue

Failure / Timeout

CATCH Scope

Identify Failed Action

Capture Error Details

Build Error Object

Generate HTML Email

Send Error Notification

TinyTake21-08-2026-02-26-18

Business Scenario

For this demonstration, we will create an employee onboarding flow.

Whenever a new employee is added to a SharePoint list, Power Automate will:

  1. Get the employee details.

  2. Create an onboarding folder.

  3. Send a welcome email.

The normal process looks like:

New Employee

Get Employee Details

Create Onboarding Folder

Send Welcome Email

If any action fails, our error handler will automatically capture the failure.

Prerequisites

For this example, you need:

Step 1 — Create the SharePoint List

Create a SharePoint list named:

Employee Onboarding

Create the following columns:

ColumnType
TitleSingle line of text
Employee EmailSingle line of text
DepartmentSingle line of text
Joining DateDate and Time
Onboarding StatusChoice

For Onboarding Status, create:

  1. Pending

  2. Processing

  3. Completed

  4. Failed

TinyTake21-08-2026-02-27-53

Step 2 — Create the Automated Flow

Create an Automated cloud flow.

Use the following name:

Employee Onboarding - Error Handling Demo

For the trigger, select:

SharePoint – When an item is created

Configure:

Site Address:
Your SharePoint Site

List Name:
Employee Onboarding

Step 3 — Rename the Trigger

Rename the trigger to:

TRG_New_Employee

Using meaningful action names is important when creating an error-handling framework because these names will later appear in our error notification.

Instead of:

When an item is created

we use:

TRG_New_Employee
TinyTake21-08-2026-02-28-42

Step 4 — Create the TRY Scope

Add:

Control → Scope

Rename it:

TRY_Process_Employee

This scope will contain our main business logic.

The structure will be:

TRY_Process_Employee
│
├── Get_Employee_Details
├── Create_Onboarding_Folder
└── Send_Welcome_Email
TinyTake21-08-2026-02-29-40

Step 5 — Get Employee Details

Inside the TRY scope, add:

SharePoint → Get item

Rename:

Get_Employee_Details

Configure:

Site Address:
Your SharePoint Site

List Name:
Employee Onboarding

Id:
ID from TRG_New_Employee

This action retrieves the complete employee record.

TinyTake21-08-2026-02-30-48

Step 6 — Create the Employee Folder

Add:

SharePoint → Create new folder

Rename:

Create_Onboarding_Folder

Configure:

Site Address:
Your SharePoint Site

List or Library:
EmployeeDocument

For the folder path, we use:

Employees/@{outputs('Get_Employee_Details')?['body/Title']}

For example:

Employees/Ismail Sayyad
TinyTake21-08-2026-02-30-59

Step 7 — Send the Welcome Email

Add:

Office 365 Outlook → Send an email (V2)

Rename:

Send_Welcome_Email

Example configuration:

To:

Employee Email

Subject:

Welcome to the Team

Body:

Hello,

Welcome to the team!

Your employee onboarding process has been initiated successfully.

Regards,
HR Team
TinyTake21-08-2026-02-31-14

Step 8 — Test the TRY Scope

Before implementing error handling, test the normal scenario.

Create an employee:

Employee Name:
Ismail Sayyad

Employee Email:
[email protected]

Department:
IT

Joining Date:
25-Aug-2026

The flow should execute successfully:

TRG_New_Employee             ✅
       ↓
Get_Employee_Details         ✅
       ↓
Create_Onboarding_Folder     ✅
       ↓
Send_Welcome_Email           ✅
TinyTake21-08-2026-02-33-20

Step 9 — Create the CATCH Scope

Now we will implement the error-handling framework.

Outside the TRY scope, add:

Control → Scope

Rename:

CATCH_Error_Handler

The flow now contains:

TRY_Process_Employee

CATCH_Error_Handler
TinyTake21-08-2026-02-34-10

Step 10 — Configure Run After

Open the three-dot menu on:

CATCH_Error_Handler

Select:

Configure run after

Enable:

☑ has failed
☑ has timed out

Leave the other options unchecked for this example.

This means:

TRY succeeds
     ↓
CATCH doesn't execute

TRY fails
     ↓
CATCH executes

TRY times out
     ↓
CATCH executes
TinyTake21-08-2026-02-34-50

Step 11 — Get Failed Actions

Inside the CATCH scope, add:

Data Operation → Filter array

Rename:

Filter_Failed_Actions

For From, use:

result('TRY_Process_Employee')

Then use advanced mode:

@equals(item()?['status'], 'Failed')

This filters the actions inside our TRY scope and keeps only failed actions.

TinyTake21-08-2026-02-35-25

Step 12 — Get the Failed Action Name

Add:

Data Operation → Compose

Rename:

Compose_Failed_Action

Use:

if(
    greater(length(body('Filter_Failed_Actions')), 0),
    first(body('Filter_Failed_Actions'))?['name'],
    'Unknown'
)

If:

Create_Onboarding_Folder

fails, the Compose action returns:

Create_Onboarding_Folder
TinyTake21-08-2026-02-37-53

Step 13 — Capture the Error Message

Add another Compose:

Compose_Error_Message

Use:

first(
    split(
        first(body('Filter_Failed_Actions'))?['outputs']?['body']?['message'],
        'clientRequestId:'
    )
)

This extracts the useful error message while removing technical identifiers such as:

clientRequestId
serviceRequestId

For our SharePoint failure, the result becomes:

The file or folder name contains characters that are not permitted. Please use a different name.

Step 14 — Capture the Flow Name

For this demonstration, create:

Compose

Rename:

Compose_Flow_Name

Value:

Employee Onboarding - Error Handling Demo

For a production framework, this can later be moved into configuration or an environment variable.

TinyTake21-08-2026-02-38-43

Step 15 — Capture the Run ID

Add:

Compose

Rename:

Compose_Run_ID

Expression:

workflow()?['run']?['name']

Example:

08584143084564250373668121992CU19

The Run ID is useful because it allows the support team to identify the exact execution that failed.

Step 16 — Capture the Timestamp

Add:

Compose

Rename:

Compose_Error_Timestamp

Expression:

convertTimeZone(
    utcNow(),
    'UTC',
    'India Standard Time',
    'dd-MMM-yyyy HH:mm:ss'
)

Example:

21-Aug-2026 13:17:10

Step 17 — Capture the Status Code

Add:

Compose

Rename:

Compose_Status_Code

Expression:

first(body('Filter_Failed_Actions'))?['outputs']?['statusCode']

For our SharePoint error:

400

Step 18 — Create the Flow URL

Add a Compose:

Compose_Flow_URL

For this demonstration, use your flow's URL:

https://make.powerautomate.com/environments/default-53c989d3-ab06-4edc-8157-06d8640eea7f/flows/d7c723d7-ba25-4f8a-a931-00423bda820e/details

In a production solution, avoid hardcoding environment-specific URLs and use configuration/environment variables where appropriate.

Step 19 — Configure the Environment

Create a string variable:

EnvironmentName

Value:

Production

Rename the action:

Initialize_Environment

In a proper Solution-based implementation, this should eventually be replaced with an Environment Variable.

TinyTake21-08-2026-02-39-31

Step 20 — Create the Error Object

Add a Compose:

Compose_Error_Object

Use:

{
  "FlowName": "@{outputs('Compose_Flow_Name')}",
  "RunId": "@{outputs('Compose_Run_ID')}",
  "FlowUrl": "@{outputs('Compose_Flow_URL')}",
  "FailedAction": "@{outputs('Compose_Failed_Action')}",
  "StatusCode": "@{outputs('Compose_Status_Code')}",
  "ErrorMessage": "@{outputs('Compose_Error_Message')}",
  "Timestamp": "@{outputs('Compose_Error_Timestamp')}",
  "Environment": "@{variables('EnvironmentName')}"
}

The final object contains all the information required for troubleshooting.

TinyTake21-08-2026-02-40-12

Step 21 — Create the HTML Error Email

Add:

Data Operation → Compose

Rename:

Compose_HTML_Error_Email

Use the HTML notification we created earlier.

The important part for the clickable Flow URL is:

<a href="@{outputs('Compose_Flow_URL')}"
   target="_blank"
   style="display:inline-block;background:#0078d4;color:#ffffff;text-decoration:none;padding:12px 26px;border-radius:5px;font-size:14px;font-weight:600;">
    Open Flow
</a>

The recipient will see an Open Flow button rather than a long URL.

Step 22 — Send the Error Notification

Add:

Office 365 Outlook → Send an email (V2)

Rename:

Send_Error_Notification

Configure:

To:

Your support/admin email

Subject:

[Power Automate Failure] @{outputs('Compose_Flow_Name')}

Body:

Outputs of Compose_HTML_Error_Email
TinyTake21-08-2026-02-42-16

Step 23 — Test the Complete Error Framework

Now intentionally create the failure again.

For example:

Employees/Error Test User:Invalid

The flow should execute:

TRG_New_Employee
        ✅
        ↓
TRY_Process_Employee
        │
        ├── Get_Employee_Details       ✅
        │
        ├── Create_Onboarding_Folder   ❌
        │
        └── Send_Welcome_Email         ⏭️
        ↓
CATCH_Error_Handler
        ✅
        ↓
Filter_Failed_Actions
        ✅
        ↓
Compose_Failed_Action
        ✅
        ↓
Compose_Error_Message
        ✅
        ↓
Compose_Error_Object
        ✅
        ↓
Compose_HTML_Error_Email
        ✅
        ↓
Send_Error_Notification
        ✅
TinyTake21-08-2026-02-43-15

Step 24 — Final Email

The support team should receive an email similar to:

🔴 Power Automate Flow Failure

Flow Information

Flow Name
Employee Onboarding - Error Handling Demo

Environment
Production

Failed Action
Create_Onboarding_Folder

Status Code
400

Run ID
08584143084564250373668121992CU19

Failure Time
21-Aug-2026 13:17:10


Error Details

The file or folder name contains characters
that are not permitted. Please use a different name.

                 [ Open Flow ]

The Open Flow button should open the Power Automate flow directly.

TinyTake21-08-2026-02-44-08

Final Architecture

At the end, your framework looks like:

TRG_New_Employee
        │
        ▼
Initialize_Environment
        │
        ▼
┌─────────────────────────────────┐
│ TRY_Process_Employee            │
│                                 │
│ Get_Employee_Details            │
│ Create_Onboarding_Folder        │
│ Send_Welcome_Email              │
└───────────────┬─────────────────┘
                │
          Failed / Timeout
                │
                ▼
┌─────────────────────────────────┐
│ CATCH_Error_Handler             │
│                                 │
│ Filter_Failed_Actions           │
│ Compose_Failed_Action           │
│ Compose_Error_Message           │
│ Compose_Flow_Name               │
│ Compose_Run_ID                  │
│ Compose_Error_Timestamp         │
│ Compose_Status_Code             │
│ Compose_Flow_URL                │
│ Compose_Error_Object            │
│ Compose_HTML_Error_Email        │
│ Send_Error_Notification        │
└─────────────────────────────────┘

Conclusion

A production Power Automate flow should not simply tell the support team that "the flow failed."

A useful error-handling framework should provide enough information to answer:

By using Scopes, Configure Run After, result(), expressions, structured error objects, and HTML email notifications, we can create a reusable error-handling pattern that can be applied to multiple production flows.