---
title: Error Handling in AEM
description: Technical Architect Juan Ayala published an article about how to handle errors in AEM. Good news...it is simple!
image: https://blog.3sharecorp.com/hubfs/ice-cream-spill.png
---

[![3SHARE_LOGO_WHITE_2018](https://blog.3sharecorp.com/hs-fs/hubfs/2017%20Website%20Assets/Logos/High%20Res/3SHARE_LOGO_WHITE_2018.png?width=266&height=54&name=3SHARE_LOGO_WHITE_2018.png "3SHARE_LOGO_WHITE_2018")](https://www.3sharecorp.com)

![ice cream cone on side with ice cream spilled](https://blog.3sharecorp.com/hubfs/ice-cream-spill.png)

# Error Handling in AEM

Juan Ayala, January 27, 2022

Recently, I worked on an AEM project that included a lot of legacy code. Some of this code involved error handling and based on its git history, it pre-dated ACS Commons. For perspective, the [ACS Commons Page Error Handler](https://adobe-consulting-services.github.io/acs-aem-commons/features/error-handler/index.html) has been an AEM feature since version [1.0.0](https://github.com/Adobe-Consulting-Services/acs-aem-commons/releases/tag/acs-aem-commons-1.0.0) in 2013! 

The client knew they needed its error handling capability to function well going forward and my task was to determine if the legacy code could be built upon or if it should be replaced with something new. 

This got me thinking about one of the oldest topics in AEM and in computer programming for that matter…error handling. As I write this it is still January 2022 so let’s start off the new year with a review!

## Why customize error messaging?

A “404” or page not found error is quite common and something a site visitor will encounter eventually. The default 404 page on an AEM publish instance looks like the below:![](https://lh5.googleusercontent.com/R7n0KilFiuJ2T1k5_MuniMALN59gF-GpH6PBGNQYhcrVInnIKhujnGV4y1Pu-SN18pFMKfXkGjOjeANStRTnOVqavZZ1M00lMwELemtW_pA0YpxYpUPYCerAtMeHZMnJkNcJjesC)

And on the author instance, it looks like this:![Screencap of text on screen "no resource found"](https://lh6.googleusercontent.com/E4gYiMFDXq43y-psMCgDR8VAi4qSp0yVBftJEgA-9hmO-cncpx9ZV3C1LVUFjEIHCIgTONLe9z3j2MoBl3qTZI2VCfdj-uMPCWZjqNpg74ILXKmeYuTt-W6XLd9Asri7zgFqAWP4)

Again, we ask the question, why customize the error messaging?

- **Don’t give away unnecessary information.** On the publish page, giving away as little as “Apache Sling” to would-be attackers could end badly. Giving away the stack trace on the author page is even worse. Granted, there are other ways to find out if a site is running AEM. And your author instance is behind a firewall. As long as none of your content authors are hackers by night, the risk isn’t great but there is a risk.
- **Error pages should be branded and friendly.** If a user navigates to a page that is no longer active (or is erroring out) you still want to keep the user on your site. At minimum, the site logo and navigation should be present to keep them on the site. There is also an opportunity to guide the user to alternative pages when they hit an error. Otherwise, they may leave and never come back!
- **Content authors should be able to edit error pages.** AEM is a content management system after all. Content authors should be able to update the content of an error page, in any language for any of the sites hosted on your instance or sections and areas within those sites.
- **Look like a pro!** If I land on your site and I see one of the above pages, you would look like an amateur. It would make me uncomfortable. I would not be creating an account, much less giving you my credit card info. I would leave and never come back.

Compared to other development tasks, setting up error handling in AEM is trivial. It boils down to some config files and a couple of overlays. Because it is such an old topic you may find some outdated information when you search for it. Even the video for the [ACS Commons Page Error Handler](https://adobe-consulting-services.github.io/acs-aem-commons/features/error-handler/index.html) is a bit outdated. 

Now, I’ll walk through the modernized version of how to do this.

### Required Content Pages

There are two ways to set up error handling. Regardless of which one you choose, you will need landing pages for your errors. Typically you only need one for 500 errors and one for a 404 error. And on a multi-language site, there is a set of these per language root in a folder called *errors*. So for example the pages below could be created to address most errors:

- /content/mysite/**us/en**/errors/404.html
- /content/mysite/**us/en**/errors/500.html

There is nothing special about these pages. They can be created with static or dynamic templates.

### Error Handling on Apache

To do this, you need to configure the dispatcher module so it does not spool errors and instead delegates to Apache. Apache will need a map of error codes and their corresponding content paths.

First, set the [*DispatcherPassError*](https://experienceleague.adobe.com/docs/experience-manager-dispatcher/using/getting-started/dispatcher-install.html?lang=en#apache-web-server-configure-apache-web-server-for-dispatcher) module parameter to 1. This will tell the dispatcher module that if it receives a response >= 400, it should delegate it to Apache.

Second, Apache will need to know what to do to serve. Use the [*ErrorDocument*](https://httpd.apache.org/docs/2.4/custom-error.html) to tell it where to fetch the error pages for each code. Assuming a multilingual content structure, place the following directives in your VHost.

```
SetEnvIf Request_URI "^/([a-z]{2})/([a-z]{2})/.*" ERRORDOCS=$1/$2/errors
SetEnvIfExpr "%{ENV:ERRORDOCS} =~ /^$/" ERRORDOCS=us/en/errors
ErrorDocument 500 /%{ENV:ERRORDOCS}/500.html
ErrorDocument 404 /%{ENV:ERRORDOCS}/404.html
```

This diagram represents the path of a 404 response:  
![Mapping of 404 and caches](https://lh6.googleusercontent.com/SQF1x_ywEAZTE261oHdtQqpZZVnbL0tiNO4TtPhxr80GwGTu3RgEgxB7gHsCXN0Faue1DBvt74vJmFggz8wTnzs_x5wC12_dUTlg-GfUoYc85sX7_3-iZP5Wk2HV_fSR-jP6mEZO)

The benefit to this setup is that the dispatcher will only fetch the error page once, and cache it. If a 404/500 error is ever encountered again, it will NOT reach back to the publisher and make it render the page again. This will guard your site against a distributed denial-of-service (DDoS) attack too.

It’s that simple; a couple of content pages, one dispatcher parameter and a few apache directives.

### Error Handling in Sling

Alternatively, you may prefer the Sling method rather than the previously described Apache method.

To do this, you need to [overlay the default scripts](https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/implementing/developing/full-stack/custom-error-page.html) and start writing your custom code. But who has time for all that code when ACS commons already has it? In case this is your preferred method, let me describe it below.

First, make sure the [*DispatcherPassError*](https://experienceleague.adobe.com/docs/experience-manager-dispatcher/using/getting-started/dispatcher-install.html?lang=en#apache-web-server-configure-apache-web-server-for-dispatcher) module parameter is 0. Unlike the dispatcher configuration above, this ensures that the dispatcher module will spool the error and not tell Apache about it.

Second, overlay the following files just as stated in their [instructions](https://adobe-consulting-services.github.io/acs-aem-commons/features/error-handler/index.html).

- /apps/sling/servlet/errorhandler/404.jsp
  
  ```
  <%@page session="false"%><%%><%@include file="/apps/acs-commons/components/utilities/errorpagehandler/404.jsp" %>
  ```
- /apps/sling/servlet/errorhandler/default.jsp
  
  ```
  <%@page session="false"%><%%><%@include file="/apps/acs-commons/components/utilities/errorpagehandler/default.jsp" %>
  ```

Finally, update your page properties dialog. Add a property called *errorPages*. The ACS error handler uses this inheritable property to determine where to get error content pages

The ACS instructions are somewhat outdated because they are still using a Classic UI example. Also, this step is very subjective. Everyone’s setup is different. Since overlaying the scripts above affect the entire instance, I chose to add it to all pages that fall under the basic page hierarchy. I overlaid the file responsible for the *Advanced* tab by creating the following.

- /apps/wcm/foundation/components/basicpage/v1/basicpage/tabs/advanced/.content.xml
  
  ```
  <?xml version="1.0" encoding="UTF-8"?><jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"jcr:primaryType="nt:unstructured">    <items jcr:primaryType="nt:unstructured">        <column                jcr:primaryType="nt:unstructured">            <items jcr:primaryType="nt:unstructured">                <section1 jcr:primaryType="nt:unstructured">                    <items jcr:primaryType="nt:unstructured">                        <errorPages                                jcr:primaryType="nt:unstructured"                                sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"                                fieldLabel="Error Pages"                                name="./errorPages"                                nodeTypes="cq:Page"                                rootPath="/content">                            <granite:data                                    jcr:primaryType="nt:unstructured"                                    cq-msm-lockable="errorPages"/>                        </errorPages>                    </items>                </section1>            </items>        </column>    </items></jcr:root>
  ```

The overlay + resource merger allowed me to insert that field within a specific section of an OOTB page properties tab.

![Screencap of AEM Web Console showing Error Page Handler Cache](https://lh5.googleusercontent.com/FYshUFsBlcxo_K5klq5MjPpThzy6Me3enSrghBdzPu8WKEhW33vYkhM0biIshsdTElSk3AZTjK7ShW2clwCBd2eXZNMNhgGD0CncITNoC0Px4uszhl2IleaSTTFibey7hHHWppwT)

This is a diagram that represents the path of a 404 response:

![Mapping of 404 and caches](https://lh5.googleusercontent.com/0nLE5CrHLOaXhErkDfipOMFfTudcVGDNME1LGp0ZZbyQOvenYalY6VPxoqekiRd5qygoGtHHU3HuCTSVZw7FkUpgBW7KiwexfR6ptlaWJyuvCYeJnd3bm2cho90o10iBmH4Yzqy_)

1. A user requests a page.
2. The dispatcher doesn’t have it so it asks the publish.
3. The publish doesn’t have it so it sends back a 404.
4. The dispatcher will not cache error responses, so it serves it right away.

The benefit to this approach is flexibility. You can write code to do anything you need to do and ACS has done this by implementing a lot of features. For example, the author controls the source of error pages through the page property. And, there is an in-memory cache to guard against DDoS. Navigate to the JMX console to view cache entries.

![](https://lh3.googleusercontent.com/Z06BZOEmWRuf5LVMZXt9Nkp0joDde51DoYyUstMYWBnoUlXVfim8jM0SJgp0MDBflS6L_9ouVv0hIHt1IoupS9Sd2DfjbtmJOQx1ESZRxjGim0F4ER7mhUJ6IeS_NWx5zCRRamtJ)

### Error Handling at the Component Level

ACS commons has two error handlers. The [error page handler](https://adobe-consulting-services.github.io/acs-aem-commons/features/error-handler/index.html) (the one above) and the [component error handler](https://adobe-consulting-services.github.io/acs-aem-commons/features/component-error-handler/index.html). They do not depend on each other.

If for some reason a component has an error, the exception will get handled gracefully. Take for example this HTL component.

```
<div data-sly-use.model="com.mysite.core.models.HelloWorldModel">    <!-- More code here --></div>
```

If the model’s *@PostConstruct* throws an exception, there will be no visual cue to let the content author know. And then what do authors usually do? Try to drop it in a few more times.

The only way for you to see the exception on the author would be to open the Developer mode.

All you need to do is enable the handler and adjust the ranking of the WCM Developer Mode Filter.

- com.adobe.acs.commons.wcm.impl.ComponentErrorHandlerImpl.cfg.json
  
  ```
  {
      "edit.enabled": true
  }    
  ```
- com.day.cq.wcm.core.impl.WCMDeveloperModeFilter.cfg.json
  
  ```
  {
      "wcmdevmodefilter.enabled": true,
      "service.ranking:Integer": 75000
  }
  ```

The only reason I bring up this handler is to disambiguate between the two handlers ACS provides. In my opinion, this component error handler is not worth setting up. Good design and code analyzers should help avoid things like null pointer exceptions, the biggest cause of component failure IMHO.

### Conclusion

When it comes to handling errors in Sling or Apache, my personal preference is Apache. The Sling approach is way more flexible, but, I prefer to keep things simple. Typically, a 404 and 500 page per site and per locale is enough.

Are you thinking about making some changes to your AEM implementation? 3|SHARE would love to help.  [Contact us!](https://www.3sharecorp.com/contact)

Hero Photo by [Sarah Kilian](https://unsplash.com/@rojekilian?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/error?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

Topics: [Development](https://blog.3sharecorp.com/topic/development), [Adobe](https://blog.3sharecorp.com/topic/adobe), [Tech](https://blog.3sharecorp.com/topic/tech), [Customer Experience](https://blog.3sharecorp.com/topic/customer-experience), [Apache](https://blog.3sharecorp.com/topic/apache)

- [Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https://blog.3sharecorp.com/error-handling-in-aem&display=popup&ref=plugin)
- [Share on Twitter](https://www.twitter.com/home?status=Error%20Handling%20in%20AEM%20-%20https://blog.3sharecorp.com/error-handling-in-aem)
- [Share on LinkedIn](https://www.linkedin.com/shareArticle?mini=true&url=https://blog.3sharecorp.com/error-handling-in-aem&title=Error%20Handling%20in%20AEM&summary=&source=)

### [Juan Ayala](https://blog.3sharecorp.com/author/juan-ayala)

Juan Ayala is a Technical Architect at 3|SHARE. He boasts three Adobe Experience Manager certifications: Dev/Ops Engineer, Sites Architect and Sites Developer. His favorite thing about being on the 3|Share is that he is able to do relevant, cutting-edge work that keeps him engaged. Outside of work, Juan enjoys DIY, motorcycling and rescuing dogs from the pound.

[LinkedIn](https://www.linkedin.com/in/ayalaj/)

### Popular Posts

### Posts by Topic

- [Adobe Experience Manager (48)](https://blog.3sharecorp.com/topic/adobe-experience-manager)
- [AEM (33)](https://blog.3sharecorp.com/topic/aem)
- [Adobe (20)](https://blog.3sharecorp.com/topic/adobe)
- [Development (19)](https://blog.3sharecorp.com/topic/development)
- [Digital Marketing (19)](https://blog.3sharecorp.com/topic/digital-marketing)
- [Tech (15)](https://blog.3sharecorp.com/topic/tech)
- [Web Content Management System (13)](https://blog.3sharecorp.com/topic/web-content-management-system)
- [3|SHARE Insider (12)](https://blog.3sharecorp.com/topic/3share-insider)
- [Developer Think Tank (12)](https://blog.3sharecorp.com/topic/developer-think-tank)
- [Digital Asset Management (DAM) (10)](https://blog.3sharecorp.com/topic/digital-asset-management-dam)
- [Professional IT Consulting Services (10)](https://blog.3sharecorp.com/topic/professional-it-consulting-services)
- [Adobe Solutions Partner (8)](https://blog.3sharecorp.com/topic/adobe-solutions-partner)
- [Creative Process (7)](https://blog.3sharecorp.com/topic/creative-process)
- [CMS (6)](https://blog.3sharecorp.com/topic/cms)
- [Content Management System (6)](https://blog.3sharecorp.com/topic/content-management-system)
- [Upgrade (6)](https://blog.3sharecorp.com/topic/upgrade)
- [Content Supply Chain (5)](https://blog.3sharecorp.com/topic/content-supply-chain)
- [Culture (5)](https://blog.3sharecorp.com/topic/culture)
- [Customer Experience (5)](https://blog.3sharecorp.com/topic/customer-experience)
- [Remote Operations Management (ROM) (5)](https://blog.3sharecorp.com/topic/remote-operations-management-rom)
- [Testing (5)](https://blog.3sharecorp.com/topic/testing)
- [Webinars (5)](https://blog.3sharecorp.com/topic/webinars)
- [AI (4)](https://blog.3sharecorp.com/topic/ai)
- [Adobe Summit (4)](https://blog.3sharecorp.com/topic/adobe-summit)
- [Personalization (4)](https://blog.3sharecorp.com/topic/personalization)
- [Sanity (4)](https://blog.3sharecorp.com/topic/sanity)
- [Structured Data (4)](https://blog.3sharecorp.com/topic/structured-data)
- [Design (3)](https://blog.3sharecorp.com/topic/design)
- [Headless (3)](https://blog.3sharecorp.com/topic/headless)
- [Leadership (3)](https://blog.3sharecorp.com/topic/leadership)
- [Quality Assurance (3)](https://blog.3sharecorp.com/topic/quality-assurance)
- [AEM Smart Tags (2)](https://blog.3sharecorp.com/topic/aem-smart-tags)
- [Award (2)](https://blog.3sharecorp.com/topic/award)
- [Content Fragments (2)](https://blog.3sharecorp.com/topic/content-fragments)
- [Evolve (2)](https://blog.3sharecorp.com/topic/evolve)
- [Evolve19 (2)](https://blog.3sharecorp.com/topic/evolve19)
- [Integrations (2)](https://blog.3sharecorp.com/topic/integrations)
- [Migration (2)](https://blog.3sharecorp.com/topic/migration)
- [QA (2)](https://blog.3sharecorp.com/topic/qa)
- [UX (2)](https://blog.3sharecorp.com/topic/ux)
- [AEM as a Cloud Service (1)](https://blog.3sharecorp.com/topic/aem-as-a-cloud-service)
- [AWS (1)](https://blog.3sharecorp.com/topic/aws)
- [Accessibility (1)](https://blog.3sharecorp.com/topic/accessibility)
- [Adobe Center of Excellence (1)](https://blog.3sharecorp.com/topic/adobe-center-of-excellence)
- [Apache (1)](https://blog.3sharecorp.com/topic/apache)
- [CDN (1)](https://blog.3sharecorp.com/topic/cdn)
- [ContextHub (1)](https://blog.3sharecorp.com/topic/contexthub)
- [CraftCMS (1)](https://blog.3sharecorp.com/topic/craftcms)
- [Digital Commerce (1)](https://blog.3sharecorp.com/topic/digital-commerce)
- [Digital Experience Solution Partner of the Year (1)](https://blog.3sharecorp.com/topic/digital-experience-solution-partner-of-the-year)
- [Extracirricular (1)](https://blog.3sharecorp.com/topic/extracirricular)
- [Invasion Test (1)](https://blog.3sharecorp.com/topic/invasion-test)
- [LLM (1)](https://blog.3sharecorp.com/topic/llm)
- [Microdata (1)](https://blog.3sharecorp.com/topic/microdata)
- [Rich Snippets (1)](https://blog.3sharecorp.com/topic/rich-snippets)
- [SEO (1)](https://blog.3sharecorp.com/topic/seo)
- [Security (1)](https://blog.3sharecorp.com/topic/security)
- [Vanity URL (1)](https://blog.3sharecorp.com/topic/vanity-url)
- [Web Server (1)](https://blog.3sharecorp.com/topic/web-server)
- [Workfront (1)](https://blog.3sharecorp.com/topic/workfront)

[see all](https://blog.3sharecorp.com/error-handling-in-aem#)

[![3SHARE_LOGO_WHITE_2018](https://blog.3sharecorp.com/hs-fs/hubfs/2017%20Website%20Assets/Logos/High%20Res/3SHARE_LOGO_WHITE_2018.png?width=266&height=54&name=3SHARE_LOGO_WHITE_2018.png "3SHARE_LOGO_WHITE_2018")](http://3sharecorp.com)

** [info@3sharecorp.com](mailto:info@3sharecorp.com)

** [US: +1 (888) 505-1625](tel:+18885051625)[tel:08003689636](tel:08003689636)

 

[**](https://www.linkedin.com/company/3-share-corporation) [**](https://www.youtube.com/@3share)

Copyright © 2026 [3|SHARE](https://www.3sharecorp.com/). All Rights Reserved.

[Cookie Settings](https://blog.3sharecorp.com/error-handling-in-aem#) ![](https://px.ads.linkedin.com/collect/?pid=8732449&fmt=gif)