Most automation demos are built around success. A record arrives, a rule evaluates, another system is updated and a notification is sent. Real operations are less polite. APIs time out, credentials expire, required fields disappear, a platform rejects an action, a human changes a record halfway through a run or a downstream system accepts a request without returning a usable confirmation.
If the workflow has no designed response to those conditions, the business has not removed manual work. It has hidden manual work behind an automated interface and made the failure harder to see.
The failure path is part of the workflow, not an exception to the workflow.
The important question is not whether failures happen
They will. The useful design question is what the system should do next. Microsoft's Power Automate guidance on error handling, for example, describes "run after" settings that define what happens when an action fails, times out or is skipped, try-and-catch scopes, retry policies and a Terminate action for stopping a flow deliberately. Those features exist because failures need deliberate handling rather than an assumption that the next action will simply run.
The business consequence matters more than the technical label. A failed report refresh is different from an uncertain payment action. A delayed internal notification is different from an order that may have been created twice. Failure handling therefore has to be designed around business state and business risk.
Why failure paths get left out
Failure handling is rarely omitted through carelessness. It is omitted because the happy path is what the business asked for, what the demo showed and what the test data exercised. Building the failure path means thinking about states that have not happened yet, and the effort does not show up as visible functionality. Low-code platforms make the happy path quick to assemble, which can make the remaining work feel disproportionate. The cost appears later, usually as silent failures that someone discovers downstream.
Define the failure classes before building the response
A practical automation usually needs to distinguish at least four conditions: a transient technical failure that may be retried; a permanent input or permission failure that needs correction; an uncertain outcome where the external action may or may not have completed; and a business exception where the process cannot continue without judgment.
Those categories should lead to different responses. Blind retries are inappropriate for permanent errors. An uncertain side effect should trigger a state check before another write. A business exception may need a person with the right context, not another technical attempt.
| Failure class | Illustrative example | Sensible response |
|---|---|---|
| Transient | Service busy or temporarily unavailable | Retry with increasing delay, up to a limit |
| Permanent | Missing mandatory field, revoked permission | Stop, record, route for correction |
| Uncertain | Request timed out after it may have been processed | Check state before any further write |
| Business exception | Order exceeds credit limit, conflicting instructions | Pause and escalate to a person with authority |
Retries need judgment, not just configuration
Microsoft's Azure Architecture Center description of the Retry pattern is a useful reference here. It distinguishes cancelling an operation when the fault is not transient, retrying immediately for rare faults and retrying after a delay for busy or connectivity failures, with delays that can increase incrementally or exponentially. It also warns that an aggressive retry policy can further degrade a busy service, and that if an operation is not idempotent, retries can cause it to run more than once. A service might process a request successfully but fail to send a response, and the retry then repeats work that was already done.
That last point is the heart of the uncertain-outcome problem. Our article on designing retries without creating duplicate work covers idempotency and state checks in more depth.
The same pattern guidance recommends logging early failed attempts as informational and only the final failure as an error, so operators are not flooded with alerts about problems that resolved themselves.
An illustrative example
The following is a hypothetical scenario, not a client case. A wholesaler automates purchase orders: when stock falls below a threshold, a workflow creates an order in the supplier's portal. One evening the portal is slow. The request times out, the workflow retries twice, and each attempt actually succeeds on the supplier's side. Three identical orders arrive. Nobody notices until three deliveries do.
A designed failure path would have treated the timeout as an uncertain outcome, checked the portal for an existing order with the same reference before retrying, and escalated to a buyer if the state could not be confirmed.
Make recovery observable
A failure path should record enough evidence to reconstruct what happened: workflow instance, step, time, relevant business identifier, error class, retry count, resulting external identifier where available, and final disposition. Logging sensitive data indiscriminately is not good control; recording the minimum evidence needed to operate the process is. Microsoft's guidance also cautions that excessive custom logging can itself become an anti-pattern that degrades a workflow.
This connects directly to automation observability. Monitoring tells you something went wrong. A failure path determines what happens after detection.
Assign ownership before the first incident
Every production automation should answer: who receives the exception, who can make the business decision, who can repair the automation, and who decides when it is safe to resume? A generic alert sent to a crowded channel is not ownership.
Escalation also needs timing. If an automated process is business-critical, define when an unresolved exception becomes an incident and when management visibility is required. That expectation should be proportionate to the business impact rather than copied from an arbitrary technology service level. Our article on service levels for business-critical automations discusses how to set those expectations.
Recovery is where duplicates are made
Resubmitting a failed run feels like the obvious fix. Microsoft's guidance on testing cloud flows warns that resubmitting can duplicate data or emails if the flow creates records or sends messages, and advises making sure error handling addresses whatever caused the original failure first. Safe resumption is a design decision, not a button.
Warning signs
- Failure alerts go to the person who built the automation and nobody else.
- The standard fix for any failure is to "rerun it".
- Staff keep side spreadsheets to track what the automation missed.
- Nobody can say how many runs failed last month or why.
- Retries are configured identically for every action, regardless of what it does.
- Testing covered only valid inputs and available systems.
A simple failure-path design
- Identify every step that can stop or produce an uncertain outcome.
- Classify the likely failure as transient, permanent, uncertain or business-exception.
- Define whether the system retries, checks state, stops, compensates or escalates.
- Preserve a reliable operation or transaction identifier.
- Route the exception to a named operational owner.
- Record the evidence needed to diagnose and recover.
- Define the conditions for safe resumption.
- Test the failure path deliberately before launch.
The trade-offs
Failure handling adds build time, testing effort and complexity. Not every automation needs the full treatment: a flow that posts a daily summary to a team channel can fail loudly and be rerun with little harm. The investment should scale with consequence. Anything that moves money, creates commitments to customers or suppliers, or changes records other systems rely on deserves explicit failure classes, state checks and a named owner.
What better looks like
A mature automation does not pretend failure is rare. It contains failure. It knows when to retry, when not to retry, when to ask a human, how to prove what happened and how to resume without duplicating or losing work.
That is the difference between automating a task and engineering an operating process.
Sources and further reading
- Employ robust error handling - Power Automate (last verified 10 October 2026)
- Retry pattern - Azure Architecture Center (last verified 10 October 2026)
- Test cloud flows - Power Automate (last verified 10 October 2026)