Error Handling — Scopes, Try-Catch, and Retry Policies
Why Error Handling Matters in Production
In production workflows, failures are inevitable. External APIs go down, data formats change unexpectedly, and network timeouts occur. Without proper error handling, a single failed action can leave your workflow in an inconsistent state — data partially processed, downstream systems out of sync, and no visibility into what went wrong.
Robust error handling ensures:
- Resilience: Workflows recover gracefully from transient failures
- Observability: Teams are notified immediately when issues arise
- Data integrity: Partial failures don't corrupt business data
- Compliance: Audit trails capture failure details for regulatory requirements
Scope Action (Grouping Actions)
A Scope is a container action in Logic Apps that groups multiple actions together. Think of it as a logical block — similar to curly braces {} in programming languages.
Key characteristics:
- Scopes can contain any number of actions, including nested scopes
- A scope's status reflects the aggregate result of its child actions
- If any child action fails, the scope itself is marked as Failed
- Scopes enable structured error handling by providing a single point to check success or failure

{
"Try_Scope": {
"type": "Scope",
"actions": {
"Get_Record": { "type": "ApiConnection", "inputs": { "..." } },
"Transform_Data": { "type": "Compose", "inputs": { "..." } },
"Update_Database": { "type": "ApiConnection", "inputs": { "..." } }
}
}
}
Try-Catch Pattern Using Scope + Run After Configuration
Logic Apps implements the Try-Catch pattern by combining Scopes with Run After configuration. This gives you the same structured error handling you'd find in traditional programming languages.
The pattern consists of:
- Try Scope — Contains the main business logic
- Catch Scope — Runs only when the Try Scope fails; handles the error
- Finally Scope — Runs regardless of outcome; performs cleanup

Run After Settings
Every action in Logic Apps can be configured with Run After settings that determine when it executes relative to the preceding action. The four statuses are:
| Status | Description |
|---|---|
| Succeeded | The previous action completed successfully (default) |
| Failed | The previous action failed with an error |
| Skipped | The previous action was skipped (e.g., condition not met) |
| Timed Out | The previous action exceeded its timeout limit |
You can select multiple statuses. For a Catch Scope, configure it to run after the Try Scope has Failed, Timed Out, or both.

To configure Run After in the designer:
- Click the three dots (
...) on the Catch Scope action - Select Configure run after
- Check has failed and has timed out
- Uncheck is successful
Retry Policies
Retry policies handle transient failures automatically before escalating to your error handling logic. Logic Apps supports four retry policy types:
None
No retries. The action fails immediately on the first error.
"retryPolicy": {
"type": "none"
}
Fixed Interval
Retries at a consistent interval between attempts.
"retryPolicy": {
"type": "fixed",
"count": 3,
"interval": "PT30S"
}
Exponential Backoff
Increases the wait time between retries exponentially, reducing pressure on struggling services.
"retryPolicy": {
"type": "exponential",
"count": 4,
"interval": "PT10S",
"maximumInterval": "PT1H",
"minimumInterval": "PT5S"
}
Custom
Define specific intervals for each retry attempt.
"retryPolicy": {
"type": "custom",
"count": 3,
"intervals": ["PT10S", "PT30S", "PT1M"]
}

Step-by-Step: Build a Workflow with Try, Catch, and Finally Scopes
Step 1: Create the Try Scope
- Add a new Scope action and rename it to
Try - Inside the scope, add your business logic actions:
- HTTP action to call an external API
- Parse JSON to process the response
- Insert Row to save data to a database

Step 2: Create the Catch Scope
- After the Try scope, add another Scope and rename it to
Catch - Configure Run After on the Catch scope:
- Uncheck is successful
- Check has failed
- Check has timed out
- Inside the Catch scope, add error handling actions:
- Compose action to capture the error using
result('Try')expression - Send an email or Post to Teams with error details
- Optionally Insert Row to log the error to a tracking table
- Compose action to capture the error using

Step 3: Create the Finally Scope
- After the Catch scope, add a third Scope and rename it to
Finally - Configure Run After on the Finally scope:
- Check is successful
- Check has failed
- Check has skipped
- Check has timed out
- Inside the Finally scope, add cleanup actions:
- HTTP action to release locks or close connections
- Compose action to log the final workflow status

Step 4: Test the Workflow
- Save and run the workflow with valid inputs — verify the Try scope succeeds and Finally runs
- Introduce a failure (e.g., invalid URL) — verify the Catch scope executes and Finally still runs
- Check that error notifications are received
Terminate Action
The Terminate action immediately ends the workflow run with a specified status:
- Succeeded — Marks the run as successful
- Failed — Marks the run as failed with an error code and message
- Cancelled — Marks the run as cancelled
Use Terminate inside your Catch scope to explicitly mark the workflow as failed after handling the error:
{
"Terminate_Failed": {
"type": "Terminate",
"inputs": {
"runStatus": "Failed",
"runError": {
"code": "ExternalAPIFailure",
"message": "The payment gateway API returned a 503 error after 3 retries."
}
}
}
}

Sending Error Notifications
Email Notifications (Office 365 Outlook)
Inside your Catch scope, add a Send an email (V2) action:
- To: ops-team@contoso.com
- Subject:
Logic App Failed: @{workflow().name} - Body: Include the error details from
result('Try')
Workflow: @{workflow().name}
Run ID: @{workflow().run.name}
Timestamp: @{utcNow()}
Error: @{result('Try')?[0]?['error']?['message']}
Microsoft Teams Notifications
Add a Post message in a chat or channel action:
- Team: Operations
- Channel: Alerts
- Message: Format with Adaptive Card for rich error details

Real-World Error Handling Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Logic App Workflow │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ TRY SCOPE │ │
│ │ ┌──────────┐ ┌──────────────┐ ┌───────────────┐ │ │
│ │ │ Call API │──▶│ Transform │──▶│ Save to DB │ │ │
│ │ │(Retry:3) │ │ Data │ │ │ │ │
│ │ └──────────┘ └──────────────┘ └───────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ Failed/Timed Out │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ CATCH SCOPE (Run After: Failed, Timed Out) │ │
│ │ ┌──────────┐ ┌──────────────┐ ┌───────────────┐ │ │
│ │ │ Capture │──▶│ Log Error │──▶│ Notify Team │ │ │
│ │ │ Error │ │ to Table │ │ (Email/Teams) │ │ │
│ │ └──────────┘ └──────────────┘ └───────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌───────────────┐ │ │
│ │ │ Terminate │ │ │
│ │ │ (Failed) │ │ │
│ │ └───────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ Always │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ FINALLY SCOPE (Run After: All statuses) │ │
│ │ ┌──────────────┐ ┌──────────────────────────────┐ │ │
│ │ │ Release │──▶│ Log Final Status │ │ │
│ │ │ Resources │ │ │ │ │
│ │ └──────────────┘ └──────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
