10.2 On-Error Continue vs. On-Error Propagate Mechanisms

Key Takeaways

  • On-Error Continue (<on-error-continue>) intercepts an error, executes its child processors, and marks the flow execution status as SUCCESS (recovering from the error), returning an HTTP 200 OK by default to HTTP Listener callers.
  • On-Error Propagate (<on-error-propagate>) intercepts an error, executes its child processors, and RE-THROWS the error up the call stack, marking the flow execution status as ERROR and returning an HTTP 500 Server Error by default to HTTP Listener callers.
  • In a parent-child flow invocation via Flow Reference (<flow-ref>), if the child flow handles an error with On-Error Continue, the parent flow resumes normal sequential processing of downstream components.
  • If a child flow handles an error with On-Error Propagate, the parent flow's remaining processors are immediately aborted, and execution jumps directly to the parent flow's own error handler.
  • In transactional flows, On-Error Continue causes an active transaction to COMMIT, whereas On-Error Propagate forces the active transaction to ROLLBACK.
Last updated: August 2026

On-Error Continue vs. On-Error Propagate Mechanisms

In Mule 4, every flow and subflow handles exceptions using one or more error scopes placed inside an <error-handler> container. The Mule runtime provides two fundamentally distinct error handling scopes: <on-error-continue> and <on-error-propagate>.

The choice between these two scopes determines whether an error is swallowed/handled (converting failure into success) or re-thrown/bubbled up the invocation stack. Mastering their exact runtime semantics, response status codes, and call-stack interactions is the single most heavily tested error handling topic on the MuleSoft Developer certification.


1. Architectural Execution Models

When an error occurs inside a flow, execution immediately jumps from the failing processor to the flow's <error-handler>. The runtime evaluates declared error scopes sequentially to find the first matching <on-error-*> block. Once matched, the child processors inside that scope execute.

What happens after the error scope finishes executing depends entirely on whether the scope is continue or propagate:

+---------------------------------------------------------------------------------------------------+
|                             ON-ERROR CONTINUE VS ON-ERROR PROPAGATE                               |
|                                                                                                   |
|   === ON-ERROR CONTINUE ===                                                                       |
|   [Error Occurs]                                                                                  |
|         |                                                                                         |
|         v                                                                                         |
|   [Execute <on-error-continue> processors]                                                        |
|         |                                                                                         |
|         +--> Status Flag = SUCCESS                                                                |
|         +--> HTTP Listener Response: HTTP 200 OK (default)                                        |
|         +--> Parent Flow (<flow-ref>): Continues to next downstream processor                    |
|         +--> Active Transaction: COMMITS                                                          |
|                                                                                                   |
|   =============================================================================================   |
|                                                                                                   |
|   === ON-ERROR PROPAGATE ===                                                                      |
|   [Error Occurs]                                                                                  |
|         |                                                                                         |
|         v                                                                                         |
|   [Execute <on-error-propagate> processors]                                                       |
|         |                                                                                         |
|         +--> Status Flag = ERROR (Re-throws exception)                                            |
|         +--> HTTP Listener Response: HTTP 500 Server Error (default)                              |
|         +--> Parent Flow (<flow-ref>): Aborts downstream processors, triggers parent error handler|
|         +--> Active Transaction: ROLLS BACK                                                       |
+---------------------------------------------------------------------------------------------------+

2. On-Error Continue Mechanics

The <on-error-continue> scope behaves like a traditional catch block that catches and fully resolves an exception. It "heals" the flow failure.

Execution Lifecycle:

  1. Catches Error: Matches the error based on type or when condition.
  2. Executes Processors: Runs all child processors inside the <on-error-continue> block (e.g., <set-payload>, <logger>, <set-variable>).
  3. Updates Event State: The payload, attributes, and vars modified inside the scope become the current event state.
  4. Sets Success Result: The runtime marks the flow execution as SUCCESSFUL.
  5. Caller Behavior:
    • If the flow was initiated by an HTTP Listener, the listener executes its Success Response configuration (returning HTTP 200 OK and the payload generated in the error scope by default).
    • If the flow was called by another flow via <flow-ref>, control returns to the parent flow, which continues executing its next downstream processor normally.

XML Example:

<flow name="get-user-profile-flow" doc:name="Get User Profile Flow">
    <http:listener config-ref="HTTP_Listener_config" path="/profile" doc:name="Listener"/>
    
    <http:request config-ref="User_Service_HTTP_Config" path="/users/details" method="GET" doc:name="Get Details"/>
    <logger level="INFO" message="Profile fetched successfully" doc:name="Log Success"/>
    
    <error-handler>
        <on-error-continue type="HTTP:NOT_FOUND" doc:name="On Error Continue: Fallback">
            <logger level="WARN" message="User profile not found. Returning guest profile." doc:name="Log Warn"/>
            <!-- Set a fallback payload -->
            <set-payload value="#[{ 'userId': 'GUEST', 'role': 'ANONYMOUS', 'status': 'DEFAULT' }]" doc:name="Set Guest Payload"/>
        </on-error-continue>
    </error-handler>
</flow>

Outcome: If /users/details returns HTTP 404, <on-error-continue> catches it, logs a warning, sets the guest payload, and returns HTTP 200 OK with the guest JSON body to the client.


3. On-Error Propagate Mechanics

The <on-error-propagate> scope catches the error, performs error processing (such as logging or formatting a standard error JSON response), and then re-throws the error to the caller.

Execution Lifecycle:

  1. Catches Error: Matches the error based on type or when condition.
  2. Executes Processors: Runs all child processors inside the <on-error-propagate> block.
  3. Re-Throws Error: The runtime marks the flow execution as FAILED / ERROR and re-throws the error up the call stack.
  4. Caller Behavior:
    • If the flow was initiated by an HTTP Listener, the listener executes its Error Response configuration (returning HTTP 500 Server Error by default, or the status mapped in the error response settings).
    • If the flow was called by another flow via <flow-ref>, the parent flow immediately halts downstream processing and routes execution into the parent flow's own error handler.

XML Example:

<flow name="process-payment-flow" doc:name="Process Payment Flow">
    <http:listener config-ref="HTTP_Listener_config" path="/checkout" doc:name="Listener"/>
    
    <http:request config-ref="Payment_Gateway_HTTP_Config" path="/charge" method="POST" doc:name="Charge Card"/>
    <logger level="INFO" message="Payment successfully charged" doc:name="Log OK"/>
    
    <error-handler>
        <on-error-propagate type="ANY" doc:name="On Error Propagate: Log and Rethrow">
            <logger level="ERROR" message="#['Payment processing failed: ' ++ error.description]" doc:name="Log Failure"/>
            <!-- Set standardized error payload -->
            <set-payload value="#[{ 'error': 'PAYMENT_FAILED', 'description': error.description, 'timestamp': now() }]" doc:name="Set Error Payload"/>
            <set-variable variableName="httpStatus" value="502" doc:name="Set HTTP 502"/>
        </on-error-propagate>
    </error-handler>
</flow>

Outcome: If the payment gateway fails, <on-error-propagate> logs the failure, sets the error payload, and re-throws the error. The HTTP Listener sends an HTTP 500 (or HTTP 502 if mapped to vars.httpStatus) to the caller.


4. Comprehensive Comparison Matrix: Continue vs. Propagate

Dimension<on-error-continue><on-error-propagate>
Flow Result StatusSUCCESS (Error is handled and cleared)ERROR (Error is re-thrown)
Re-throwing BehaviorDoes NOT re-throw; flow finishes as success.Re-throws the error to caller / parent flow.
Parent Flow Execution (via <flow-ref>)Parent flow CONTINUES executing next downstream processors.Parent flow ABORTS remaining processors and enters parent's error handler.
Default HTTP Listener Status CodeHTTP 200 OKHTTP 500 Server Error
HTTP Listener Response PathTriggers HTTP Listener Responses (Success) tab.Triggers HTTP Listener Error Responses tab.
Response Body Returned to ClientOutput payload of <on-error-continue>.Default error.description or current payload (if configured in Error Response tab).
Transaction HandlingActive transaction COMMITS.Active transaction ROLLS BACK.
Typical Architectural Use CasesDefault/fallback responses, caching fallbacks, non-critical service degradation, batch item error swallowing.Strict business validation failures, fatal backend connectivity loss, transaction aborts, global error mapping.

5. Flow-to-Flow Interaction Scenarios & Call Stacks

Understanding multi-flow call stacks is essential for the exam. Let's analyze how errors propagate across flow boundaries.

Scenario A: Parent Calls Child with On-Error Continue

[Client Request] ---> [HTTP Listener (/order)]
                            |
                   [mainFlow Begins]
                   1. <set-variable variableName="orderId" value="'ORD-99'" />
                   2. <flow-ref name="childPaymentFlow" />
                            |
                            v
                   [childPaymentFlow Begins]
                   1. <http:request> (Throws HTTP:CONNECTIVITY!)
                   2. [childPaymentFlow Error Handler]
                      -> Matches <on-error-continue type="HTTP:CONNECTIVITY">
                      -> <set-payload value="'PAYMENT_PENDING'" />
                      -> [Exits child flow with STATUS = SUCCESS]
                            |
                            v
                   [mainFlow Resumes]
                   3. <logger message="Processing finished: #[payload]" /> (EXECUTES!)
                   4. [mainFlow Finishes Successfully]
                            |
                            v
[HTTP Listener Returns]: HTTP 200 OK, payload = 'PAYMENT_PENDING'

Scenario B: Parent Calls Child with On-Error Propagate

[Client Request] ---> [HTTP Listener (/order)]
                            |
                   [mainFlow Begins]
                   1. <set-variable variableName="orderId" value="'ORD-99'" />
                   2. <flow-ref name="childPaymentFlow" />
                            |
                            v
                   [childPaymentFlow Begins]
                   1. <http:request> (Throws HTTP:CONNECTIVITY!)
                   2. [childPaymentFlow Error Handler]
                      -> Matches <on-error-propagate type="HTTP:CONNECTIVITY">
                      -> <logger message="Child error logged" />
                      -> [Exits child flow with STATUS = ERROR (RE-THROWN)]
                            |
                            v
                   [mainFlow Interrupted!]
                   3. <logger message="Processing finished" /> (NEVER EXECUTES!)
                   4. [mainFlow Error Handler Triggered!]
                      -> Matches <on-error-propagate type="ANY">
                      -> <set-payload value="'MAIN_FLOW_ERROR'" />
                            |
                            v
[HTTP Listener Returns]: HTTP 500 Server Error (or configured error response)

Scenario C: Parent Has On-Error Continue Catching Child's On-Error Propagate

If childPaymentFlow uses <on-error-propagate> and re-throws the error, but mainFlow handles the re-thrown error using <on-error-continue>:

  • mainFlow's remaining flow processors are skipped.
  • mainFlow's <on-error-continue> executes and sets payload to 'RECOVERED_IN_MAIN'.
  • mainFlow completes as SUCCESS.
  • The HTTP Listener returns HTTP 200 OK with payload 'RECOVERED_IN_MAIN'.

6. HTTP Listener Responses Configuration

By default, the HTTP Listener component is configured as follows:

  • Responses (Success Tab):
    • Body: #[payload]
    • Status Code: 200
  • Error Responses (Error Tab):
    • Body: #[error.description]
    • Status Code: 500
<http:listener config-ref="HTTP_Listener_config" path="/api/orders" doc:name="Listener">
    <http:response statusCode="#[vars.httpStatus default 200]">
        <http:body>#[payload]</http:body>
    </http:response>
    <http:error-response statusCode="#[vars.httpStatus default 500]">
        <http:body>#[payload default error.description]</http:body>
    </http:error-response>
</http:listener>

[!IMPORTANT] Returning Custom Error Payloads with On-Error Propagate Notice that if you use default HTTP Listener settings and <on-error-propagate>, setting <set-payload> inside <on-error-propagate> will not be returned to the client because the default error response body is #[error.description]. To return the payload created in <on-error-propagate>, configure the HTTP Listener Error Response body to #[payload].


7. Exam Watch: Core Decision Rules

[!IMPORTANT] The "What is the HTTP Status Code?" Rule

  • If the error handler that finally finishes the request contains <on-error-continue>, the default HTTP response status code is 200.
  • If the error handler that finally finishes the request contains <on-error-propagate>, the default HTTP response status code is 500.

[!WARNING] Parent Flow Continuation Rule An error in a child flow called via <flow-ref> will only allow the parent flow to continue executing downstream processors if the child flow handles the error with <on-error-continue>.

[!TIP] Flow Variable Persistence Variables (vars) created before an error occurs remain intact and accessible inside both <on-error-continue> and <on-error-propagate> scopes.

Test Your Knowledge

A parent flow mainOrderFlow starts with an HTTP Listener on /orders, sets vars.orderId = 'ORD-400', and invokes childFlow via a Flow Reference. Inside childFlow, an HTTP Request fails with an HTTP:CONNECTIVITY error. childFlow's error handler is configured with an On-Error Continue scope that sets payload = { 'status': 'QUEUED_FOR_RETRY' }. Immediately following the Flow Reference in mainOrderFlow is a Logger component. How does the execution proceed and what HTTP response is sent to the client?

A
B
C
D
Test Your Knowledge

A flow named processCustomerFlow has an HTTP Listener on /customers and calls an external CRM API. The CRM API returns an HTTP 400 Bad Request. The flow contains an error handler with an On-Error Propagate scope that catches ANY, logs the error, and sets payload = { 'error': 'INVALID_CUSTOMER_PAYLOAD' }. The HTTP Listener uses standard default settings. What HTTP status code and response body are returned to the HTTP client?

A
B
C
D
Test Your Knowledge

An integration application executes a financial transfer involving two Database Insert operations inside a transactional flow. If an unexpected database constraint error (DB:QUERY_EXECUTION) occurs during the second insert, the business requirement requires the entire transaction to ROLLBACK and the HTTP client to receive an error status. Which error handling scope should be configured in the flow's error handler?

A
B
C
D
Test Your Knowledge

Flow parentFlow calls childFlow using a Flow Reference. parentFlow is configured with an error handler containing <on-error-continue type="ANY"> that sets payload = 'HANDLED_IN_PARENT'. childFlow is configured with an error handler containing <on-error-propagate type="ANY"> that sets payload = 'ERROR_IN_CHILD'. An HTTP:TIMEOUT error occurs inside childFlow. What is the execution flow and the final payload returned to the client by parentFlow's HTTP Listener?

A
B
C
D