Authors: Nikhil Kumar & Pankuri Bansal
In this blog, we will explore the process of generic error handling framework within Mule 4. We’ll cover how to set up and execute a common error-handling framework.
Overview of Error Handling
- Gone are the days when error handling was confined to cumbersome Java exception-handling processes where you had to dig through source code or intentionally induce errors just to identify the issue.
- With advancements in technology, error management has evolved into a more sophisticated and intuitive process that doesn’t require such tedious tasks.
- In the latest version of Mule, called Mule 4, they have introduced a more streamlined and efficient way of handling errors.
- This enhancement not only saves time in troubleshooting, but also improves overall efficiency in error handling.
Importance of Error Handling Framework
- This framework is an invaluable tool for developing a generic error handler for all APIs within your project.
- By utilizing it as a plugin, you can effortlessly implement this functionality across your entire project.
Prerequisites
- Create a trial account on the Anypoint Platform.
Implementation
- Open the Anypoint Platform -> Go to Access Management
- First, create a Connected App (Go to Connected App Tab -> Click on Create App).

- Write the Name of the App and select the Type. Once that is done, click on the Save button.

- Then add the scopes as per the use case requirement.
- In this blog, we use scopes as shown below.

- Select the Business Groups.

- Select the Environments in which you are going to deploy the applications.

- Review all the details and then click on the Next button.

- Finally, the Connected APP is created for your Business Group.
- Copy Client Id and Client Secret for future use.

- Also, copy the Organization ID (Go to Access Management -> Click on Organisations Tab -> Click on Business Group).

- To get started, open Anypoint Studio and navigate to the project where you want to create a Generic Error Handler Application. In this blog, we created an application called “demo-generic-error-handler” as shown in the screenshot below.

Configuration Xml for demo-generic-error-handler app
<configuration-properties doc:name="Configuration properties" doc:id="21178f6d-3b57-46e4-85ac-7e1ba5a53563" file="property\error-handler-local.yaml" />
<error-handler name="global_error_handler">
<on-error-propagate type="APIKIT:BAD_REQUEST"
enableNotifications="true" logException="true">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="ac7ff2bd-c88e-49d0-90a6-44040bf0917d"
message='In apisero-generic-global-error-handler, CorrelationID : #[correlationId]' /> -->
<set-variable
value='${errorCodeMessage.apikit.badRequest.code}'
doc:name="httpStatus" doc:id="2bcf392c-e50a-4e06-8888-f06164189064"
variableName="httpStatus" />
<set-variable
value='${errorCodeMessage.apikit.badRequest.description}'
doc:name="errorDescription"
doc:id="c6c79e6f-00c5-4ddd-b7ef-6b06b028b701"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="464bba2d-fe07-4a1c-8a6b-7f3c8d062603"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate type="APIKIT:NOT_FOUND"
enableNotifications="true" logException="true">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="28f61c25-55d8-4cf1-bab2-0d04bc9e9f3e"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='${errorCodeMessage.apikit.notFound.code}'
doc:name="httpStatus" doc:id="d3b13aa7-76f0-4891-a261-1e3138a290f9"
variableName="httpStatus" />
<set-variable
value='${errorCodeMessage.apikit.notFound.description}'
doc:name="errorDescription"
doc:id="9d8a2a12-aa25-4c58-8d0d-0dd3ea543e27"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="0c60e8dd-f188-4dd6-a8a8-f65ba098cd4b"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate
type="APIKIT:METHOD_NOT_ALLOWED">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="8bb7e2fb-9192-4a60-8490-91b69aba3f12"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='${errorCodeMessage.apikit.methodNotAllowed.code}'
doc:name="httpStatus" doc:id="b98be123-71bb-4b6f-9919-d40fa9f955e9"
variableName="httpStatus" />
<set-variable
value='${errorCodeMessage.apikit.methodNotAllowed.description}'
doc:name="errorDescription"
doc:id="73f1922b-1528-4587-94b5-9b5360e7ea9b"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="8c970dfa-edde-4643-a087-a75282157cd2"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate type="APIKIT:NOT_ACCEPTABLE"
enableNotifications="true" logException="true">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="ecdce9e8-2b6d-4a77-9b59-68ce83d0ada0"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='${errorCodeMessage.apikit.notAcceptable.code}'
doc:name="httpStatus" doc:id="e462ca25-d2e7-4f44-9155-15e39961bbf9"
variableName="httpStatus" />
<set-variable
value='${errorCodeMessage.apikit.notAcceptable.description}'
doc:name="errorDescription"
doc:id="55ed6cc9-e794-4522-bcbd-0a695e96e83f"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="8cc63664-0ba9-4b9c-9779-0e2e90cb2782"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate
type="APIKIT:UNSUPPORTED_MEDIA_TYPE">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="cbc41f71-6aaa-4afb-ae5b-ab91c5db15d4"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='${errorCodeMessage.apikit.unsupportedMediaType.code}'
doc:name="httpStatus" doc:id="710d6012-45c9-4cdd-a25c-14f540cd2e49"
variableName="httpStatus" />
<set-variable
value='${errorCodeMessage.apikit.unsupportedMediaType.description}'
doc:name="errorDescription"
doc:id="acbbc41a-e3a7-4fc2-a07f-421b8dc81653"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="d16c6e56-0dc6-453a-bb0f-7b061bdcdf43"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate type="APIKIT:NOT_IMPLEMENTED"
enableNotifications="true" logException="true">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="553ad6a3-739e-47ec-93a7-b99e790758d3"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='${errorCodeMessage.apikit.notImplemented.code}'
doc:name="httpStatus" doc:id="4492b4a8-cb6c-49d6-a132-ad61479ce291"
variableName="httpStatus" />
<set-variable
value='${errorCodeMessage.apikit.notImplemented.description}'
doc:name="errorDescription"
doc:id="60243489-01f6-450b-a853-13a35e2b4eb7"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="dc6d6aff-1dac-49f7-b4b8-c86c929998a3"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate enableNotifications="true"
logException="true" doc:name="On Error Propagate"
doc:id="e45e55a7-bedd-4e31-91b5-4eee9748c95c"
type="HTTP:CONNECTIVITY">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="4d2e35e7-7aa1-4984-a5ff-590d99e2a66d"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler" doc:id="16194a19-b6a6-4fa4-8c47-633e7efaa340"
message='#["From parent flow" ++ (vars.apiLayer default "")]'/> <logger level="INFO"
doc:name="Entering Generic Error Handler" doc:id="d3026740-8e25-4191-a1e7-245d12f8a30e"
message="From Properties file #[p('globalErrorHandler.api-layer')]"/> -->
<set-variable
value='${errorCodeMessage.http.connectivity.code}'
doc:name="httpStatus" doc:id="fa47a8e9-7ac8-40c3-b9f3-6508583af8f6"
variableName="httpStatus" />
<set-variable
value="#[if(p('globalErrorHandler.api-layer') == "experience" or p('globalErrorHandler.api-layer') == "exp")
p('errorCodeMessage.http.connectivity.description') default ""
else
error.description default ""]"
doc:name="errorDescription"
doc:id="a4095c06-6300-481a-8d56-3e475a190761"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="d085beee-3761-42bb-9b1d-a2cbb56279d0"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate enableNotifications="true"
logException="true" doc:name="On Error Propagate"
doc:id="79669995-e617-4285-b66b-f537fa84bfee" type="HTTP:FORBIDDEN">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="3315c9d2-6703-40f1-b611-8b4e61848add"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='${errorCodeMessage.http.forbidden.code}'
doc:name="httpStatus" doc:id="19320aaa-5336-4260-8ed7-aeab295b6c09"
variableName="httpStatus" />
<set-variable
value="#[if(p('globalErrorHandler.api-layer') == "experience" or p('globalErrorHandler.api-layer') == "exp")
p('errorCodeMessage.http.forbidden.description') default ""
else
error.description default ""]"
doc:name="errorDescription"
doc:id="7cd6133e-4fc0-41f3-b80b-ee05f8a42d6c"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="0bf657b7-febc-42e7-957f-f86a4123aeae"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate enableNotifications="true"
logException="true" doc:name="On Error Propagate"
doc:id="9346fdeb-4375-4782-9511-0c7de14294ba"
type="HTTP:SERVICE_UNAVAILABLE">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="b0d0a848-9d09-494e-bae2-3ebc858b6aea"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='${errorCodeMessage.http.serviceUnavailable.code}'
doc:name="httpStatus" doc:id="e3cf629e-1a0e-430c-913b-930d84153580"
variableName="httpStatus" />
<set-variable
value="#[if(p('globalErrorHandler.api-layer') == "experience" or p('globalErrorHandler.api-layer') == "exp")
p('errorCodeMessage.http.serviceUnavailable.description') default ""
else
error.description default ""]"
doc:name="errorDescription"
doc:id="0b6b6fcb-bfa4-497d-a0ca-9e10cc213f60"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="363343dd-f40b-470e-8944-828408055f97"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate enableNotifications="true"
logException="true" doc:name="On Error Propagate"
doc:id="b28484d6-bc6d-4bcf-a88d-14a2d3e79d5c" type="HTTP:TIMEOUT">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="125d432b-c9f1-4516-a7ef-afe00a973068"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='${errorCodeMessage.http.timeout.code}' doc:name="httpStatus"
doc:id="29a32eda-a080-4ac3-95d6-87400821fb2a"
variableName="httpStatus" />
<set-variable
value="#[if(p('globalErrorHandler.api-layer') == "experience" or p('globalErrorHandler.api-layer') == "exp")
p('errorCodeMessage.http.timeout.description') default ""
else
error.description default ""]"
doc:name="errorDescription"
doc:id="335732b2-e9c7-474a-ad1d-d1b6f7ca067c"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="d674b66f-2c86-40b0-a2d6-b2c22659a5b1"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate enableNotifications="true"
logException="true" doc:name="On Error Propagate"
doc:id="f5a1602b-35c6-4301-b0b8-201d40231d6a"
type="HTTP:UNAUTHORIZED">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="f618a5aa-bad9-4a21-a09a-0a978f8191de"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='${errorCodeMessage.http.unauthorized.code}'
doc:name="httpStatus" doc:id="7c680e6b-f742-414c-8f63-f97824ec1aea"
variableName="httpStatus" />
<set-variable
value="#[if(p('globalErrorHandler.api-layer') == "experience" or p('globalErrorHandler.api-layer') == "exp")
p('errorCodeMessage.http.unauthorized.description') default ""
else
error.description default ""]"
doc:name="errorDescription"
doc:id="5a20b32c-2885-4538-aa62-3f566b405df8"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="1d6d3fc2-c064-4bbe-823e-47407558c196"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate enableNotifications="true"
logException="true" doc:name="On Error Propagate"
doc:id="c7f8320e-c741-44d4-9bd2-1d0c4bb907f1" type="MULE:VALIDATION">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="1e492ff3-4a19-4640-a78e-047f99d5752e"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='#[attributes.statusCode default 500]' doc:name="httpStatus"
doc:id="33d0a4ed-8d79-47d4-bee8-14772499400d"
variableName="httpStatus" />
<set-variable value="#[error.description]"
doc:name="errorDescription"
doc:id="99d426d5-be69-4230-b157-e5a39f893716"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="f06d256e-fdb5-460b-88d8-7bd30c373827"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate enableNotifications="true"
logException="true" doc:name="On Error Propagate"
doc:id="368d0385-b257-40c1-b26a-0c6c0df14153"
type="DB:BAD_SQL_SYNTAX, DB:CONNECTIVITY, DB:QUERY_EXECUTION, DB:RETRY_EXHAUSTED, STREAM_MAXIMUM_SIZE_EXCEEDED">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="a516cfee-c127-4f06-b1c6-b90e80e6edcb"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='#[attributes.statusCode default "500"]'
doc:name="httpStatus" doc:id="09e384f1-bf29-427a-8e04-b26a46bb87db"
variableName="httpStatus" />
<set-variable value="#[error.description]"
doc:name="errorDescription"
doc:id="8e93f2d4-a555-4718-bd05-ba55182574ca"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="dca37158-600a-4a2c-8937-d1849d7570a7"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate enableNotifications="true"
logException="true" doc:name="On Error Propagate"
doc:id="36eb5441-1462-4736-a1cd-4bf8c1b31090" type="EXPRESSION">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="64656748-8253-4138-bc85-5c06290856ef"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='#[attributes.statusCode default "500"]' doc:name="httpStatus"
doc:id="be028c09-db82-4414-936b-a5b2e1a1ec9e"
variableName="httpStatus" />
<set-variable value="#[error.description]"
doc:name="errorDescription"
doc:id="0914e8d1-ab7d-4760-9d3e-b28bc0188466"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="6c089460-aee1-495f-b751-1bf213111e72"
name="common-error-sub-flow" />
</on-error-propagate>
<on-error-propagate enableNotifications="true"
logException="true" doc:name="On Error Propagate"
doc:id="4bc4bf83-ab3c-435c-83b8-fc5345a8a6d9" type="ANY">
<!-- <logger level="INFO" doc:name="Entering Generic Error Handler"
doc:id="a59764f6-351e-434b-a594-860074036e17"
message='"In apisero-generic-global-error-handler, CorrelationID : #[correlationId]"' /> -->
<set-variable
value='#[attributes.statusCode default "500"]' doc:name="httpStatus"
doc:id="f74116e2-5938-4a92-9f1b-e2d9a7ee0d27"
variableName="httpStatus" />
<set-variable value="#[error.description]"
doc:name="errorDescription"
doc:id="8dc00c16-27ce-49a3-ba59-43cfd19e7262"
variableName="errorDescription" />
<flow-ref doc:name="common-error-sub-flow"
doc:id="498b6a25-8fcb-41a1-95da-43633160c83b"
name="common-error-sub-flow" />
</on-error-propagate>
</error-handler>
<sub-flow name="common-error-sub-flow"
doc:id="a75257a7-93a8-4b00-bb47-affc7d0cffc2">
<!-- <ee:transform doc:name="DW - Initiate Logging Variables"
doc:id="a763cdc1-71c1-445c-8e2d-acf4a7e11961">
<ee:message>
</ee:message>
<ee:variables>
<ee:set-variable variableName="log_name"><![CDATA["apisero-generic-error-handler"]]></ee:set-variable>
<ee:set-variable variableName="log_flowName"><![CDATA["common-error-sub-flow"]]></ee:set-variable>
<ee:set-variable
variableName="log_originatingApplication"><![CDATA["Generic Error Handler"]]></ee:set-variable>
<ee:set-variable
variableName="log_destinationApplication"><![CDATA["Generic Error Handler"]]></ee:set-variable>
</ee:variables>
</ee:transform> -->
<!-- <logger level="ERROR" doc:name="Log Error"
doc:id="a0c4832c-f090-4d70-bfcf-d58ae60535fd"
message='"Error - HTTP Status Code: " #[vars.httpStatus] " Error Message Description: " #[vars.errorDescription]' /> -->
<!-- <ee:transform doc:name="Error Response" doc:id="1abda29e-c587-43c4-8578-a603226ff9ba"
xsi:schemaLocation=" http://www.mulesoft.org/schema/mule/email http://www.mulesoft.org/schema/mule/email/current/mule-email.xsd
http://www.mulesoft.org/schema/mule/db http://www.mulesoft.org/schema/mule/db/current/mule-db.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd">
<ee:message> <ee:set-payload resource="dwTransformations/genericErrorResponse.dwl"
/> </ee:message> <ee:variables> </ee:variables> </ee:transform> -->
<set-payload
value="#[%dw 2.0 output application/json --- { transactionId: correlationId, errorCode: vars.httpStatus, errorMessage: vars.errorDescription, timestamp: now() }]"
doc:name="Final Error Response"
doc:id="c461e895-7c1c-462e-91e8-99d10c4be34d" />
</sub-flow>
- Now go to pom.xml
- It is important to make a change in the URL under the distributionManagement tag, specifically under the repository section. Replace the default organization ID with your Business Group’s organization ID.
<distributionManagement>
<repository>
<id>anypoint-exchange-v3</id>
<name>anypoint-exchange-v3</name>
<url>https://maven.anypoint.mulesoft.com/api/v3/organizations/${organization_id}/maven</url>
<layout>default</layout>
</repository>
</distributionManagement>
Now, Change the Password under the server tag. In the last screenshot of the connected app we got client Id and client secret. Just replace default ones with your Business Group’s client id and client secret (as shown below).
<server>
<id>anypoint-exchange-v3</id>
<username>~~~Client~~~</username>
<password>${client_id}~?~${client_secret}</password>
</server>
- Lastly, we are implementing and deploying this framework as a plugin not as an application.
So replace the application with a plugin under build tag under plugins.
<build>
<plugins>
<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-maven-plugin</artifactId>
<version>${mule.maven.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<classifier>mule-plugin</classifier>
</configuration>
</plugin>
</plugins>
</build>
- Now go to the .m2 Folder (Go to local disk -> users) and open the settings.xml file.
- It is important to refactor the local repository first.

- Make sure Anypoint Exchange version should be version 3(v3) everywhere because on CloudHub it’s going to deploy with the third version only.
Replace client Id and client secret as shown below under the server’s tag.
<servers>
<server>
<id>anypoint-exchange-v3</id>
<username>~~~Client~~~</username>
<password>${clien_id}~?~${client_Secret}</password>
</server>
</servers>
Now, replace the Organization Id under profiles tag. Especially, under the profile tag as shown below.
<profiles>
<profile>
<id>anypoint-exchange-v3</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<mulesoft.exchange.groupid>0ead117f-5fd1-461d-b57e-bc59714a6a92</mulesoft.exchange.groupid>
</properties>
<repositories>
<repository>
<id>anypoint-exchange-v3</id>
<name>anypoint-exchange-v3</name>
<url>https://maven.anypoint.mulesoft.com/api/v3/organizations/${organisation_id}/maven</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
Now, go to Project Location and open the CMD.

- Run the command “mvn deploy”.
- After this, the application is deployed successfully.

Now, you will be able to see the application on Exchange.

If not, then copy the click given on the cmd prompt once the application is deployed.

- Error Handling Framework now added as a plugin.
- So, now just create a new demo application.
- Go to Search in Exchange then search and add the app. Complete the process by clicking on “Finish”.

- You can now see that the framework has been added as a plugin in your application.

- To fully integrate this framework into your application, you must make some necessary configurations. Begin by navigating to the Global Elements settings. From there, you can begin the process of utilizing this powerful framework.
- Create Configuration and select Global error handler xml from the drop down as shown below.

- Secondly, create new configuration name as “Import”. Then search your error handler framework xml from project location.

- Xml name is even shown on the Project explorer under your demo application under the error handler framework you just imported from exchange.

Finally, you are good to start with your use case implementation.