October 4th, 2024

Streamlining Error Handling in Power Automate for Better Workflow Performance

Background

The Microsoft Power Platform is a suite of low-code tools that enables developers to rapidly build, automate, and analyze complex business processes. It provides robust capabilities for creating custom applications, automating workflows, and generating data-driven insights, enhancing productivity and innovation across organizations.

Our team recently undertook the development of a contract management system designed to streamline the workflows necessary to process requests both within our immediate organization and more broadly across Microsoft.

While the Power Platform is accessible to users with varying technical backgrounds, this project aimed to incorporate strong software engineering principles to elevate the quality of our solutions. As a result, some of the concepts highlighted in this post may be unfamiliar to those new to the platform.

A key focus of our development was leveraging low-code to ensure the system was easy to maintain, while also incorporating engineering rigor to create a solution that serves as a beacon of the platform’s capabilities.

The Problem

One of the key features we developed was to supercharge the functionality of the system by using Power Automate flows. Some of the examples of what these Power Automate flows are:

  • Capturing the time spent during each stage of a request, to track where time in the process is being spent
  • Checking what the management chain that an employee sits within, to detect if they’re within our department or elsewhere in the organization
  • Sending system messages when a change is made which requires the attention of the requestor of the contracting request.

As we developed and tested Power Automate flows, we noticed errors appearing in various actions within the flow. It was realized that for a successful production launch, it was crucial to track the frequency and location of these errors, identify necessary fixes, and present this data to management to show progress in reducing errors over a period of time.

Solution

After extensive research a number of approaches to error handling were identified which were combined into a common method which we applied across all Power Automate flows developed within our system. The following key elements make up the solution:

  • Try / Catch / Finally

    Try/Catch/Finally is a construct in programming used for error handling, where “Try” executes a block of code, “Catch” handles any errors that occur, and “Finally” executes code regardless of whether an error was caught.

  • Power Automate Functions

    Power Automate workflow functions allow you to interact programmatically with various elements of the flow, such as retrieving action details, manipulating data, and managing control logic.

  • Application Insights

    Azure Application Insights is a feature of Azure Monitor that provides powerful tools for collecting, analyzing, and acting on telemetry data from your applications, enabling you to monitor performance, diagnose issues, and gain insights into user behavior.

  • Messaging Layer

    In order to increase the immediate visibility of error messages (our App Insights Power BI Dashboard is only refresh daily) we leveraged channel messages in Microsoft Teams to alert the system maintainers of errors, so that on system launch, any errors could be quickly identified and triaged.

Try / Catch / Finally in Power Automate

Try / Catch / Finally isn’t “built in” functionality within Power Automate. The discovery of how this approach could be thought of was found in a post by Ilya Fainberg. With this in mind we developed a similar approach in Power Automate.

In Power Automate there is an action called a Scope. A Scope is a container used to group a set of actions together, allowing for better organization and control over the execution of those actions.

Power Automate Scope

In Power Automate you can configure the run after properties of actions like a Scope. Within the run after properties, you can have an action run based on whether the previous action:

  • Is successful
  • Has timed out
  • Is skipped
  • Has failed

Catch

Based on this knowledge, an arrangement of scopes was created within the flow to adopt the Try / Catch / Finally construct.

Try-Catch-Finally

The run after properties for each scope is as follows:

Scope Description Run After Condition
Catch Handles errors by running if the Try scope encounters issues Runs if the Try scope has timed out or has failed
Finally Executes final cleanup actions regardless of the Try scope’s outcome Runs if the Catch scope or Try scope is successful

With the ability to capture when actions within a flow would cause an error it was now possible to move on to the ability to identify the errors that are occurring within the flow.

Catch Error

Power Automate Functions

Power Automate functions are predefined operations used within a flow to manipulate data, perform calculations, or control flow logic. After some research and inspiration from a video by Reza Dorrani, we identified the functions that can be used to provide visibility of errors.

Step 1 – Leverage the result() function

The result() function in Power Automate retrieves the output and status of a specified action within a flow, allowing you to use this information in subsequent actions.

The output from the result() function is included below based on the example flow.

[
  {
    "name": "Try",
    "startTime": "2024-05-24T20:17:22.3977134Z",
    "endTime": "2024-05-24T20:17:22.3984752Z",
    "trackingId": "60d63741-ef31-4ee7-96f4-2986d2dc30c0",
    "clientTrackingId": "08585250250431718753124961648CU62",
    "clientKeywords": [
      "testFlow"
    ],
    "code": "BadRequest",
    "status": "Failed",
    "error": {
      "code": "InvalidTemplate",
      "message": "Unable to process template language expressions in action 'Compose' inputs at line '0' and column '0': 'The template language function 'int' was invoked with a parameter that is not valid. The value cannot be converted to the target type.'."
    }
  }
]

Within the JSON array resulting from the result() function there are key fields that can help manage errors.

  • name of the action
  • status of the action
  • error
    • code the error code of the action
    • message the error message of the action

Step 2 – Filter the result() array

Filter-Array

With the ability to return an error, it is necessary to filter the results from the Try Scope, so that we only return those which are equal to TimedOut or Failed.

This is achieved by Filtering the Array and leveraging this expression to only return the Failed and Timedout items.

or(equals(item()?['Status'], 'Failed'),equals(item()?['Status'], 'TimedOut'))

Step 3 – Get the flow name with workflow()

alt text

The result() function doesn’t include the name of the flow where the error is taking place. This can be retrieved by using another Power Automate function.

The workflow() function allows you to discover, where the flow is hosted, the environment it’s contained within, whether it is enabled or not, when it was last modified, who it was created by and the trigger type.

An example of the raw output from the workflow() function is included for reference.

{
    "id": "/workflows/6953ecc5ace8460393490e2c79943c1c",
    "name": "20fca30a-843d4-4e2b-8273-8790a473c26c",
    "type": "Microsoft.Logic/workflows",
    "location": "westeurope",
    "tags": {
        "flowDisplayName": "Button -> Try,Catch,Finally,Compose",
        "environmentName": "7ae19c59-22d0-ed07-8737-bd55c721e842",
        "logicAppName": "20fca30a-83d4-5c9b-8273-8790a473c36c",
        "environmentFlowSuspensionReason": "7ae15c59:2D22d0:2Ded07:2D8737:2Dbd55c721d742-None",
        "state": "Enabled",
        "createdTime": "5/24/2024 8:08:41 PM",
        "lastModifiedTime": "5/24/2024 8:34:25 PM",
        "createdBy": "e9e72c61-fca9-45e9-a33f-b75424d05642",
        "triggerType": "Instant"
    },
    "run": {
        "id": "/workflows/6953ecc6avd5760393490e2c79943b1c/runs/08584850239712387988582932421CU23",
        "name": "08584850238210387988582932421CU23",
        "type": "Microsoft.Logic/workflows/runs"
    }
}

To return only the flow name an adjustment to the expression will be made.

workflow()?['tags']['flowDisplayName']

Now we have the information we need, we can send this data to Azure Application Insights so that we can log our errors for reporting purposes.

Azure Application Insights

NOTE: The following approach for constructing an HTTP request for logging errors was derived from a troubleshooting article, available here. While it has proven effective, please note that it is not officially documented or supported as a standard API method. More information on the official method can be found here.

To upload errors to Application Insights, an HTTP request in Power Automate is used to post the event.

HTTP Action

The following parameters should be provided.

URI: https: //dc.services.visualstudio.com/v2/track

Method: POST

Headers:

  • Key: Content-Type Value application/json
  • Key: x-api-key
  • Key: api-key

    The x-api-key and api key can be found in the Azure Portal where you create your application insights instance.

    The x-api-key can be found on the Overview, under the Instrumentation Key

    Instrumentation-key

    The api-key can be found under the Configure, API Access. It’s important to make sure that you allow the use of Write Annotations, as this will authorize the Power Automate HTTP request to post events.

    API-key

Body:

Utilizing the values from the preceding steps is essential for the HTTP action body. These values are incorporated within the body, specified under ‘basedata’ and ‘properties’. The ‘properties’ section is customizable, and specific values are used to facilitate data tracking in reports.

Depending on your specific use case, you might find it beneficial to include additional properties, such as tracingId or clientTrackingId, which could be useful for more detailed debugging or tracking. Although these fields were not necessary for our immediate reporting needs, they might offer value in scenarios where deeper traceability is required.

  • name: The name of the flow returned from step 3
  • ActionName: The name of the error from step 2
  • Status: The status of the error from step 2
  • ErrorMessage: The message included in the error from step 2
  • WorkflowURL: A direct link to the url build based on a concatenated URL.
{
  "name": "App Insights Message Name",
  "time": "@{utcNow()}",
  "iKey": "!Insert Instrumentation Key Here!",
  "data": {
    "baseType": "EventData",
    "baseData": {
      "ver": 2,
      "name": "@{outputs('Flow_Name')}",
      "properties": {
        "ActionName": "@{first(outputs('Filter_array')?['body'])?['name']}",
        "Status": "@{first(outputs('Filter_array')?['body'])?['status']}",
        "ErrorMessage": "@{first(outputs('Filter_array')?['body'])?['error']?['message']}",
        "WorkflowURL": "@{concat('https://make.powerautomate.com/environments/', workflow()?['tags']['environmentName'], '/flows/', workflow()?['name'], '/runs/', workflow()?['run']['name'])}"
      }
    }
  }
}

The resulting HTTP action can be retrieved in the Events in Azure Application Insights.

App Insights Custom Properties

Messaging Layer

In addition to capturing events in Application Insights for reporting purposes, an additional messaging layer was added to ensure that notifications are visible directly within the team’s operating environment.

Step 1: Creating a HTML table

The first step in the messaging layer is to format the results of the error into a HTML table. This ensures that when we present the message to the team managing the maintenance of the flow, that it’s easily readable.

HTML Table

It’s important when configuring the HTML table that you use Custom, as otherwise the format of the table won’t present the key Header and Value pairs of the columns we require.

The following fields are provided for the table, similar to what is provided to Azure Application Insights.

Header Value
Action first(outputs(‘Filter_array’)?[‘body’])?[‘name’]
Status first(outputs(‘Filter_array’)?[‘body’])?[‘status’]
ErrorMessage first(outputs(‘Filter_array’)?[‘body’])?[‘error’]?[‘message’]
Workflow URL concat(‘https://make.powerautomate.com/environments/’, workflow()?[‘tags’][‘environmentName’], ‘/flows/’, workflow()?[‘name’], ‘/runs/’, workflow()?[‘run’][‘name’])
Example setup of the Create HTML table parameters provided

Create HTML table

Example output of the HTML table action
{
    "body": "<table><thead><tr><th>Action</th><th>Status</th><th>ErrorMessage</th><th>Workflow URL</th></tr></thead><tbody><tr><td>Compose</td><td>Failed</td><td>Unable to process template language expressions in action 'Compose' inputs at line '0' and column '0': 'The template language function 'int' was invoked with a parameter that is not valid. The value cannot be converted to the target type.'.</td><td>https://make.powerautomate.com/environments/7ae15c59-22d0-ed07-8737-bd55c721d742/flows/20fca30a-83d4-4d9b-8273-8790a473c25c/runs/08584844445035898792421848898CU86</td></tr></tbody></table>"
}

Step 2: Sending the error to Teams

The next step in the messaging layer is to send the error message to a Teams chat / channel where the message can be viewed by the team maintaining the system / flow.

The Post message in a chat or channel action is used, so that the html message can be rendered. We chose to post the error message in a channel as there is an option to set custom notifications and it means a group of maintainers can view the error.

The output of the Create HTML table is used as the message when configuring this action.

Configure Teams Message

The resulting message in teams renders as follows:

Teams Error Message

Step 3: Configuring Teams channel notifications

To increase the visibility of the Teams channel notifications of error associated to a flow, it’s recommended to turn on notification for a channel.

This can be done, by following these steps:

  1. Click the three dots next to the channel and select Channel Notifications.

    Channel Settings list

  2. Adjust the All new posts to Banner and Feed. This will ensure that when an error message is return it will be presented in your Teams notifications.

    Channel Notification Settings

  3. With notifications turned on you will receive push notifications to alert attention to any errors.

    Push Notification Example

Repeatability

Once the “Catch” scope has been configured this can easily be copied and pasted and applied to all the other Power Automate flows within your solution. This is achieved by setting up the Try and Finally Scope and then pasting the Catch Scope in and adjusting the Run after settings. As all of the actions are configured to run based on the information passed within that specific flow. The ability to quickly apply the pattern to all the Power Automate flows in your solution is a game-changer.

Copy Catch Action

Key Takeaways

  • Error Handling Framework: Implementing a robust error handling framework in Power Automate is crucial for ensuring the reliability and maintainability of your workflows. The Try / Catch / Finally construct, although not built-in, can be effectively implemented using Scopes and run after properties.
  • Power Automate Functions: Leveraging functions such as result() and workflow() enables detailed tracking and analysis of errors within your flows. These functions provide valuable insights into the status and specifics of actions, which is essential for diagnosing and resolving issues.
  • Azure Application Insights Integration: Integrating Power Automate with Azure Application Insights allows for centralized monitoring and reporting of errors. This integration facilitates proactive error management and continuous improvement of your workflows.
  • Real-Time Notifications: Adding a messaging layer that utilizes Microsoft Teams for real-time notifications ensures that your team is immediately alerted to any errors. This enhances the ability to quickly identify, triage, and resolve issues as they occur.
  • Repeatability and Scalability: The error handling approach discussed is not only effective but also repeatable across multiple flows. This ensures a consistent and scalable method for managing errors, which can be easily applied to any Power Automate solution.

By adopting these strategies, you can enhance the resilience and performance of your Power Automate workflows, leading to more reliable and efficient business processes.

Author