---
title: "Handling Multiple Errors in Mule with Collection Aggregator · Appnovation"
url: "https://www.appnovation.com/insights/handling-multiple-errors-mule-collection-aggregator"
description: "How to catch multiple errors in Mule ESB with a Collection Aggregator and send a single formatted email with all error details."
---

Article

# Handling Multiple Errors in Mule with Collection Aggregator

[![](https://cdn.sanity.io/images/ey850001/production/36eb314260fb474cacc1b3a473d7e8402d997898-68x68.png?w=68&auto=format) Appno Blogger Appnovation Coop](/people/appno-blogger.md) Dec 04, 2014  
 6 min read 

![Handling Multiple Errors in Mule with Collection Aggregator](https://cdn.sanity.io/images/ey850001/production/770a6141cf20b5b92fd39a795695c1030086ad00-1400x400.jpg?w=1400&auto=format) 

I recently worked with a client on a Mule ESB project that had a requirement to catch unexpected errors and send a formatted email with the error details. This requirement seemed simple enough, so we created a global exception strategy and referred to it from all of our flows. The error handler looked something like this:`<catch-exception-strategy name="catchUnexpectedError"> <parse-template location="templates/error-notification-email.txt"/> <smtp:outbound-endpoint name="unexpectedExceptionEmail" host="${email.host}" port="${email.port}" to="${error.to}" from="${error.from}" subject="${generic.error.subject}"/> </catch-exception-strategy>`What we quickly realized when we started testing the application in a test environment was that in certain "failure" situations, there were several errors that were generated. The result of this was that several error emails were being sent. This was not the desired behavior, the desired behavior was to only send one email with all of the error messages in it. So what did we do? We employed the use of a collection aggregator to collect all of the exceptions to create one single email. Here are the steps we took to accomplish this: 1. We set the MULE\_CORRELATION\_ID property in the initial flow that was being triggered.`<set-property propertyName="MULE_CORRELATION_ID" value="#[java.util.UUID.randomUUID().toString()]"/>`2\. We set the MULE\_CORRELATION\_GROUP\_SIZE property right after that.`<set-property propertyName="MULE_CORRELATION_GROUP_SIZE" value="#[java.lang.Integer.MAX_VALUE]"/>`3\. Changed the global exception strategy to look like this:`<catch-exception-strategy name="catchUnexpectedError"> <processor-chain> <collection-aggregator failOnTimeout="false" timeout="${error.aggregator.timeout}"/> <transformer ref="unexpectedErrorTransformer"/> <parse-template location="templates/error-notification-email.txt"/> <smtp:outbound-endpoint name="unexpectedExceptionEmail" host="${email.host}" port="${email.port}" to="${error.to}" from="${error.from}" subject="${generic.error.subject}"/> </processor-chain> </catch-exception-strategy>`The next time we tested the application in a scenario where several errors were generated, only one email was sent with all of the error messages in it. So, how did this work? Setting the MULE\_CORRELATION\_ID property attaches to all messages that spawn from the flow where it is set an id that "links" the messages together. Setting the MULE\_CORRELATION\_GROUP\_SIZE property tells the collection aggregator how large the collection sent to it could be. In this case, we had no clue how many possible errors could be sent, so we set this to a size that would likely never be exceeded. How would this ever work then? We set a timeout on the collection aggregator that would continue with the processing of the exception strategy even when the collection size didn't meet the size of the MULE\_CORRELATION\_GROUP\_SIZE property (which was the case in this example). Also to note, we used a custom transformer to process the message collection to set the payload for the template to be emailed. This transformer is written in Groovy and looks like this:`import groovy.util.logging.Slf4j
import org.mule.api.MuleMessage
import org.mule.api.transformer.TransformerException
import org.mule.transformer.AbstractMessageTransformer
import org.springframework.stereotype.Component
@Slf4j
@Component("unexpectedErrorTransformer")
class UnexpectedErrorTransformer extends AbstractMessageTransformer { public static final String LINE_BREAK = System.getProperty('line.separator')``` `@Override Object transformMessage(MuleMessage muleMessage, String s) throws TransformerException { org.mule.DefaultMessageCollection messageCollection = muleMessage List messages = messageCollection.messageList StringBuilder builder = new StringBuilder() int errorCount = 1 messages.collect({ builder.append(buildErrorMessage(errorCount++,it)) })` ```muleMessage.setPayload(builder.toString()) return muleMessage } String buildErrorMessage(int errorCount,MuleMessage aMessage){ StringBuilder errorMessage = new StringBuilder() errorMessage.append(errorCount + ". The following unexpected error occurred:") errorMessage.append(LINE_BREAK) errorMessage.append(aMessage.exceptionPayload?.exception?.summaryMessage) errorMessage.append(LINE_BREAK) return errorMessage.toString() }
}`Also, to give you a little more context, this is what the email template looked like: **The following unexpected error(s) have occurred: #\[payload\]** I hope that this helps you out if you ever run into a similar situation when dealing with errors in a Mule ESB project.

[![](https://cdn.sanity.io/images/ey850001/production/36eb314260fb474cacc1b3a473d7e8402d997898-68x68.png?w=68&auto=format) Appno Blogger Appnovation Coop · Appnovation](/people/appno-blogger.md) 

## Keep reading

[![What is Sovereign AI](https://cdn.sanity.io/images/ey850001/production/a5889abdd5e80376912546622e046e3fbef234b4-2496x1664.png?w=640&auto=format)](/insights/what-is-open-source-sovereign-ai.md)

 Article · 7 min AI 

### [What Is Open Source, Sovereign AI?](/insights/what-is-open-source-sovereign-ai.md)

Every company is encouraging more AI, and almost every AI bill is climbing. Sovereign AI is about two kinds of control: over your data and over your costs. Here's why open source sits at its foundation.

[Iain MacNeil](/people/iain-macneil.md) Article 

[![AI-first experience design](https://cdn.sanity.io/images/ey850001/production/8bbc2418e87924ef10f36115478a2e10d5bed95e-1584x624.jpg?w=640&auto=format)](/insights/how-build-ai-first-experience-without-throwing-out-everything-youve-already-built.md)

 Article · 6 min AI Sep 10, 2026 

### [How to Build an AI-First Experience Without Throwing Out Everything You've Already Built](/insights/how-build-ai-first-experience-without-throwing-out-everything-youve-already-built.md)

Users now expect a direct answer, not a list of links to click through. Here's how organizations can layer an AI-First experience onto their existing website or app, in weeks rather than years.

[Andrew Douglas](/people/andrew-douglas.md) Article 

[![What Becomes Possible When AI Can Read All the Data](https://cdn.sanity.io/images/ey850001/production/c28ab0bd26753421ee42937e13adc7a7f19b47f0-1296x510.jpg?w=640&auto=format)](/insights/what-becomes-possible-when-ai-can-read-all-data.md)

 Article · 4 min AI Sep 09, 2026 

### [What Becomes Possible When AI Can Read All the Data](/insights/what-becomes-possible-when-ai-can-read-all-data.md)

Most of the world's data has never been analyzed, only sampled. AI changes that. How AI-ready data platforms unlock questions no one could ask before.

[Appnovation](/people/appnovation.md) Article 

## Get the thinking,  
*before everyone else.*

One considered email a month. New essays, field notes from live engagements, and the occasional strong opinion. No noise.
