Implementing 404 error handler. | Community
Skip to main content
Level 1
April 23, 2026
Question

Implementing 404 error handler.

  • April 23, 2026
  • 3 replies
  • 16 views

404 error handler is implemented by overlaying the 404 from /libs/sling/servlet/errorhandler/404.jsp but changes 404.jsp to 404.html. And Java class to handle the request. on Dispatcher enabled below two flags
<IfModule disp_apache2.c>
        # Enabled to allow rewrites to take affect and not be ignored by the dispatcher module
        DispatcherUseProcessedURL    On
        # Default setting to allow all errors to come from the aem instance
        DispatcherPassError        1
  </IfModule>
Java class have  -

import com.adobe.cq.sightly.WCMUsePojo;

public class PageNotFound extends WCMUsePojo {

    @Override

    public void activate() throws Exception {

        getResponse().setStatus(404);

        getResponse().setContentType("text/html");

        getResponse().setHeader("Dispatcher", "no-cache");

        getResponse().setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");

        getResponse().setHeader("Pragma", "no-cache");

    }

}
And html have  -

<sly data-sly-use.pageNotFound="com.aem.core.errorHandler.PageNotFound"></sly>

<sly data-sly-resource="${'/content/aem/us/en/404/jcr:content' @ wcmmode='disabled'}"></sly>

This implementation works good on local but on qa environment it is going to default.jsp under errorhandler.

 Actula requirement is page shouldn’t redirect to 404.html but content is served from that page.

Can someone let me know the root cause for this issue?

3 replies

Mani_kumar_
Community Advisor
Community Advisor
April 23, 2026

Do not rely only 404.html.

This may be the reason local can work but QA fails. A request in QA may come through Dispatcher/rewrite with a different request form, extension, or resolution path, so your 404.html handler is not selected and Sling falls back to default.jsp. The standard documented customization path is the /apps/.../404.jsp overlay.

 

Have custom 404.html approach with /apps/sling/servlet/errorhandler/404.jsp, add /apps/sling/servlet/errorhandler/default.jsp as fallback, and include the authored 404 page content from there while keeping response status = 404.

Adobe Employee
April 23, 2026

@SaiMu1 
The most likely root cause is on the AEM/Sling error-handler side, not Dispatcher.

Your QA request is reaching Sling's error handling, but your custom 404 handler is either not being selected correctly or it is failing while rendering, so Sling falls back to the default error handler (default.jsp). That fallback behavior is standard when Sling cannot resolve a usable custom handler. The documented customization model is to overlay the error handler under /apps/sling/servlet/errorhandler, typically starting from 404.jsp, and Sling uses its normal script resolution rules to pick the handler. If no suitable handler is resolved, Sling uses the default handler.

https://experienceleague.adobe.com/en/docs/experience-manager-65/content/implementing/developing/platform/customizing-errorhandler-pages

https://sling.apache.org/documentation/the-sling-engine/errorhandling.html

 

Sanket_Kumbharkhane
Level 4
April 23, 2026

QA shows default.jsp because Sling isn’t using your custom 404 handler. When it can’t find (or can’t run) a handler for that status, it falls back to default.

Why it works locally but not on QA

  1. 404.html under errorhandler is flaky
    Docs and real-world setups assume 404.jsp. A 404.html HTL script might resolve on one environment and not another (AEM/SP version, script engines, how the node is packaged). If Sling doesn’t treat it as the 404 handler, you get default.jsp.

  2. Publish vs what you actually deployed
    Most common: the overlay (/apps/sling/servlet/errorhandler/...) and/or the bundle with PageNotFound isn’t on QA Publish the way it is locally (wrong package, runmodes, only author, etc.).

  3. Handler blows up at runtime
    If data-sly-use can’t load the class or activate() throws, the error page render can fail; then behavior gets weird. Check error.log on QA.

  4. Dispatcher flags aren’t the smoking gun
    DispatcherPassError 1 and DispatcherUseProcessedURL On don’t explain “always default.jsp” by themselves. They’re not a substitute for “handler exists and Sling resolves it.”

Probable solution: 

  • Ship a thin 404.jsp under /apps/sling/servlet/errorhandler/ that sets 404 + headers and includes/forwards to your real /content/.../404 experience (no redirect unless you add one).
  • Confirm on QA Publish: that node exists, 404.jsp is there, and the OSGi bundle with PageNotFound is active.