Error Handling in Mule 4: Try, On Error Propagate, On Error Continue
Every flow you've built so far in this series has assumed the happy path — the database is up, the API responds, the file is well-formed. Real integrations don't get that luxury. This post covers Mule 4's error handling model properly: what a Mule Error actually contains, the Try scope, and the two core error handlers you'll use constantly.
What a Mule Error Actually Is
When something goes wrong in a flow, Mule creates an error object that describes the problem — giving you a high-level overview of what happened. This error object has a few key components worth knowing:
- Description — a description of the problem, giving a high-level overview of the error's nature
- Type — categorizes the problem and allows routing within an error handler, since different error types can be handled differently
- Cause — the underlying Java exception that actually caused the failure, useful for deeper debugging
- Message — an optional message giving additional context
Error types follow a NAMESPACE:IDENTIFIER pattern — for example HTTP:CONNECTIVITY or DB:CONNECTIVITY. By default, an error handler is set to catch errors of type ANY — the parent of all error types — but you can narrow it down to handle specific error types differently, which is exactly what makes real error handling strategies possible rather than one generic catch-all. Mule 4 conveniently auto-populates the list of possible error types based on which connectors are actually used in your flow, so you're not guessing at what could go wrong.
The Try Scope: Error Handling Inside a Flow
Mule 3 mostly only allowed error handling at the whole-flow level, which forced developers to extract logic into separate flows just to handle errors around one specific step. Mule 4 introduced the Try scope specifically to fix this — letting you wrap just the components that might fail, right where they are in the flow, without needing to extract anything.
<try>
<http:request method="GET" url="https://api.example.com/data"/>
<error-handler>
<on-error-continue type="HTTP:CONNECTIVITY">
<set-payload value="Fallback response: Service unavailable"/>
</on-error-continue>
<on-error-propagate type="ANY">
<set-payload value="Unexpected error occurred"/>
</on-error-propagate>
</error-handler>
</try>
In this pattern, an On Error Propagate handler is configured for database or connectivity-type errors specifically, causing the Try to fail and the flow's own error handler to take over — while an On Error Continue handler catches everything else, letting the Try scope succeed and the flow continue on to its next step, like an HTTP Request that follows.
On Error Propagate vs On Error Continue: The Core Distinction
This is the single most important concept in this post, so it's worth being very precise:
| On Error Propagate | On Error Continue | |
|---|---|---|
| What it does | Processes the error message and re-throws the error up to the parent flow | Catches the error and does NOT report it as an error — flow processing continues normally |
| Result of the containing scope | Treated as failed | Treated as successful |
| Transaction behavior | Rolled back | Committed |
| Use when | You want the caller/parent to know something failed | You have a genuine fallback and want the flow to complete normally |
The mental model that makes this click: On Error Continue doesn't just handle the error quietly — it tells Mule "this step succeeded, actually" and lets everything downstream run as if nothing went wrong (using whatever payload the error handler sets). On Error Propagate says the opposite: "this genuinely failed, and I'm telling whoever called me."
A Worked Example: Choosing the Right Handler
Picture our Product API from earlier in this series, calling an external pricing service:
<try>
<http:request method="GET" path="/pricing/{id}"/>
<error-handler>
<on-error-continue type="HTTP:CONNECTIVITY">
<ee:transform>
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{ price: null, priceSource: "unavailable" }]]></ee:set-payload>
</ee:message>
</ee:transform>
</on-error-continue>
</error-handler>
</try>
Here, On Error Continue makes sense: if the pricing service is briefly unreachable, we'd rather return the product with a "price unavailable" note than fail the entire request. Compare that to a payment-processing step, where a failure should almost certainly use On Error Propagate — you don't want to silently continue as if a payment succeeded when it didn't.
This is the actual skill: choosing which handler fits each specific failure, not memorizing the syntax. Error handling isn't just a technical feature — it's a design decision about what your integration should do when things go wrong,</cite> and that decision is different for every step in every flow.
Global Error Handlers
For errors that aren't caught by any Try scope or flow-level handler, Mule falls back to a default error handler. You can also define your own global error handler — a reusable error-handling configuration referenced across multiple flows, useful for consistent behavior (like always logging errors the same way, or always returning the same error response shape to callers) without repeating the same error-handler block in every flow.
What's Next
Handling errors gracefully is half of building reliable integrations. The other half is proving your flows actually work correctly in the first place — before they ever hit production.
Next up in this series: Introduction to MUnit: Testing Your Mule Flows
visit ebook site - https://techebooks.myinstamojo.com/
0 Comments