Templates & Frontend
Build a Custom Error Page in Your Joomla Template
The default error page has nothing to do with your design, and a visitor who hits a broken link gets dropped onto something that looks like a different site. Joomla lets a template supply its own error.php, complete with navigation. Here…
Start from the system file
Copy the fallback error page into your own template as a starting point:
cp templates/system/error.php templates/yourtemplate/error.php
From here on you are editing your template's copy. Joomla picks it up automatically — there is nothing to register.
Bring in your layout
Copy the markup from your template's index.php into error.php, then adjust the parts that cannot work the same way. Two things change.
The component placeholder. There is no component on an error page, so replace it with the error itself:
<?php echo $this->error->getCode(); ?>
<?php echo htmlspecialchars($this->error->getMessage(), ENT_QUOTES, 'UTF-8'); ?>
Escape the message. It can carry text you did not write, and this page is rendered outside the usual output filtering.
Module positions. jdoc:include type="modules" is not processed here either. Render the modules you want by hand:
use Joomla\CMS\Helper\ModuleHelper;
$module = ModuleHelper::getModule('mod_menu', 'Main Menu');
if ($module) {
echo ModuleHelper::renderModule($module);
}
The first argument is the module type, the second its title as set in the module manager. Check the result before echoing it: a renamed or unpublished module returns nothing, and an unguarded call will emit a warning on a page that exists precisely to handle failure.
If a guide tells you to call jimport() first, ignore it: classes are autoloaded, and the namespaced helper above is the whole of it.
Assets need to be loaded explicitly
This is the part that catches people out. The error page runs outside the normal document pipeline: plugins do not process it, and whatever your optimisation plugin normally does — combining CSS, deferring scripts, injecting fonts — does not happen here.
Link your stylesheets and scripts directly in the <head> of error.php. If you rely on the web asset manager elsewhere, this page will not follow it.
Test it properly
Request a URL that genuinely does not exist and confirm two things: the page looks right, and the response code is actually 404. A styled error page that returns 200 is worse than an ugly one — search engines will index it as a real page, and you end up with hundreds of near-identical entries in the index.
Check a 403 and a 500 as well if your template branches on getCode(). Those paths are easy to get wrong because you see them far less often.