A finance manager submits a purchase requisition through a Power Automate approval flow on a Friday afternoon. The flow’s run history shows a clean green checkmark. Nobody gets an error notification. Nobody gets paged. And nobody notices that the requisition is still sitting in “Waiting for approval” three weeks later, because the connection that created the flow belonged to an employee who left the company the same week the flow ran. The flow didn’t crash. It just stopped being able to reach the approver, and the default configuration had no mechanism to tell anyone that had happened. This is the gap that Power Automate error handling, done properly, is supposed to close, and it’s a gap that most approval flows in production today were never built to cover.
This is the failure mode that makes approval flows uniquely dangerous among Power Automate use cases. A malformed SharePoint update or a broken HTTP call to an external API tends to fail loudly and immediately, inside a run that someone is watching because they just triggered it. An approval flow fails quietly, often days or weeks after it started, to an audience that has already moved on to something else. Power Automate error handling for approval-heavy processes has to account for that gap between when something breaks and when a human would otherwise notice, and the out-of-the-box behavior of a cloud flow does very little to close it.
What Actually Breaks an Approval Flow
Before building an error-handling pattern, it helps to know what you’re actually defending against, because the failure modes for approvals are more specific than generic connector errors. Microsoft’s own troubleshooting documentation for flow approvals names two conditions directly tied to the connection that created the approval: ApprovalConnectionOwnerNotFoundInGraph, which fires when the account that owns the Approvals connection has been deleted from Microsoft Entra ID, and ApprovalConnectionOwnerNotEnabledInGraph, which fires when that account still exists but has been disabled. Both are common consequences of ordinary offboarding, and both will stop an approval flow cold with no warning to the requester or the intended approver.
A second cluster of failures involves timing. ActionTimedOut occurs when a “Wait for an approval” action’s configured timeout expires before a decision is made, and OperationTimedOut shows up on longer-running processes that exceed the platform’s maximum flow run duration of thirty days. Left at their defaults, many approval actions simply run until someone acts on them or the flow hits that ceiling, which means a request can sit unresolved for weeks without the flow itself ever reporting an error, because from the platform’s perspective nothing has technically gone wrong yet.
A third category sits at the connection layer more broadly: InvalidConnection and ConnectionAuthorizationFailed errors, which surface when a password reset, an expired OAuth token, or a Conditional Access policy change invalidates the credentials a flow depends on. Microsoft’s guidance on broken connections is blunt about the underlying cause, noting that connections tied to individual user accounts break whenever that account’s password changes or the account is disabled, which makes personal connections a structurally poor choice for anything running unattended in production.
Why Power Automate Error Handling Doesn’t Happen by Default
The reason none of this shows up as a visible incident is that Power Automate’s default run-after configuration only wires one path: continue if the previous action succeeded. There’s no branch for failure unless you explicitly add one, and there’s no notification unless you explicitly build it. A flow that fails at the approval step simply shows a red icon in a run history that, realistically, nobody is checking unless they already suspect something is wrong. For a process with dozens or hundreds of concurrent approval instances across an organization, that’s not a monitoring gap. It’s the absence of monitoring entirely.
This is precisely the situation Microsoft’s own coding guidance addresses through Run After configuration, and it’s worth treating as the non-negotiable baseline for any approval flow that matters to the business, not an optional hardening step reserved for critical systems.

Building the Scope-Based Try, Catch, Finally Pattern
The standard architecture for this, and the one Microsoft’s guidance points toward, wraps the core approval logic in three scopes. The first, a “Try” scope, contains the actual approval request, the wait, and whatever downstream actions execute once a decision comes back. The second, a “Catch” scope, is configured through Run After to execute when the Try scope has failed, has timed out, or was skipped, which are the three states that indicate something went wrong rather than simply concluded. Inside the Catch scope, the result() expression combined with a Filter Array action pulls the specific error code and message out of the failed action, which is what lets a notification say “the approval connection owner was removed from Entra ID” instead of a generic “something failed.”
A third scope, often labeled “Finally,” is configured to run after the Catch scope regardless of outcome, meaning after it has succeeded, failed, timed out, or been skipped. This is where cleanup and status logging belong, because it executes whether the Try scope worked cleanly or not, which keeps your audit trail complete instead of only recording the failure path.
For notification and logging, Microsoft’s guidance is explicit that Application Insights should be the default target rather than writing to a SharePoint list or a Dataverse table with a dedicated logging flow, both because it avoids the performance cost of excessive custom logging and because it consolidates monitoring across many flows into one queryable location instead of scattering it flow by flow. The workflow() function is useful here too, since it returns the run’s ID and environment metadata, which you can use to build a direct link to the failed run and drop it straight into a Teams message or an email to whoever owns the process.
Hardening the Approval Action Itself
Beyond the general try/catch pattern, approval actions specifically benefit from three adjustments that are easy to skip during initial flow design. First, set an explicit timeout on the “Wait for an approval” action rather than leaving it at the default, and pair that timeout with a Run After branch that fires on “has timed out.” That branch should escalate, typically to a backup approver, a manager one level up, or a distribution list, rather than simply notifying that the deadline passed and leaving the request unresolved. Second, configure retry policies on the connector actions surrounding the approval, using an exponential backoff pattern (an initial interval that doubles or triples with each attempt, up to a defined cap) so that transient throttling from Microsoft Graph or Dataverse doesn’t get treated the same as a permanent failure.
Third, and most important given how often it’s the actual root cause, move production approval flows off personal connections entirely. A connection reference paired with a service principal, rather than a connection tied to whoever happened to build the flow, means the flow keeps running when that person changes teams, resets a password, or leaves the company, which directly eliminates the ApprovalConnectionOwnerNotFoundInGraph and ApprovalConnectionOwnerNotEnabledInGraph failure modes described earlier. This is also an offboarding process question as much as a technical one: whoever manages user departures needs to know which production flows depend on that person’s connections before the account gets disabled, not after an approval silently stalls.
Testing Failure Paths on Purpose
None of this is verified until you’ve actually watched it fail. Before a flow goes into production, it’s worth deliberately breaking it: disable a test account that owns a connection and confirm the Catch scope actually catches it, set an artificially short approval timeout and confirm the escalation branch fires, and revoke a connection mid-run to see whether the resulting error surfaces somewhere a person will actually see it. Teams tend to build the happy path carefully and assume the failure path will behave the same way, which is rarely true the first time it’s tested. A flow checker pass and a clean test run through the approval itself tell you almost nothing about how the flow behaves once something upstream goes wrong, and that’s exactly the scenario a production approval process will eventually face.
The Takeaway
Approval flows fail differently than most other automation, because the cost of an undetected failure compounds silently while everyone assumes the process is working. The fix isn’t exotic: Run After branching, a Try/Catch/Finally scope structure, retry policies with backoff, connection references instead of personal accounts, and centralized logging through Application Insights. What it requires is treating error handling as part of the initial build rather than a patch applied after the first incident. At Routeget Technologies, the approval flows we get called in to fix almost never fail because the underlying logic was wrong. They fail because nobody built a path for the flow to tell anyone it had a problem.
#PowerAutomate #ApprovalWorkflows #FlowErrorHandling #ConnectionOwnership #PowerPlatformGovernance #EnterpriseAutomation
