Error Pages
Error pages live in resources/views/errors/. Laravel renders {status}.blade.php for an HTTP error with that status. They use one of two layouts, depending on whether the application can be trusted to work when the error happens.
| Page | View | Layout |
|---|---|---|
| 401, 402, 403, 404, 419, 429 | <x-error-layout title="..."> | The public layout |
| 503 (maintenance, external service outage) | <x-error-layout title="..." :navigation="false"> | <x-layouts.error> |
| 500 | Its own body | <x-layouts.error> |
| Database paused | Its own body | <x-layouts.error> |
Client Errors on the Public Layout
Section titled “Client Errors on the Public Layout”<x-error-layout> (App\View\Components\ErrorLayout) renders resources/views/errors/layout.blade.php: a heading from title, the slot as the message, and a Back to Homepage button. By default it renders on the public layout, so the header keeps the Help menu and Sign In or the user menu, and the page uses the app panel’s theme.
The public layout looks up the signed-in user inside rescue(), so a failing lookup leaves the page signed out instead of failing it. A fallback route sends unknown URLs through the web middleware, so the not-found page knows who is signed in.
The Error Layout
Section titled “The Error Layout”<x-layouts.error> (resources/views/components/layouts/error.blade.php) renders the pages that can’t rely on the application working: 500, 503 and database-paused. It must work when nothing else does:
- It loads no Filament, makes no auth calls and doesn’t touch the database.
- Its styles come from
resources/css/errors.css, which imports Tailwind and the Northwestern design tokens directly instead of a panel theme. - It renders
<x-site-header>without a Help menu or user menu, and the Northwestern footer.
<x-error-layout :navigation="false"> uses this layout. The 503 page passes it, because maintenance mode and outages are exactly when the panel and the database may be unavailable.
Adding or Changing an Error Page
Section titled “Adding or Changing an Error Page”-
Edit the message of an existing client error in its view, for example
resources/views/errors/404.blade.php:<x-error-layout title="Page Not Found">We can't find that page. Check the address and try again.</x-error-layout> -
Add a page for another status as
resources/views/errors/{status}.blade.php. Use<x-error-layout>, and pass:navigation="false"when the error means the application itself may not be working. -
Cover a whole range with
4xx.blade.phpor5xx.blade.php. Laravel falls back to them when no view matches the exact status. Without one, a status such as 405 renders Laravel’s plain error page. -
Check it in the browser tests. Add the status to the list in the error page test in
tests/Browser/Pages/PublicPagesTest.php.ErrorPages::path($status)registers a test route that answers with that status, so pages only a failure shows are checked too. See Browser Tests.
Both resources/css/filament/app/theme.css and resources/css/errors.css compile classes from resources/views/errors/, so new views there need no @source change.
The 500 Page
Section titled “The 500 Page”resources/views/errors/500.blade.php renders for unhandled exceptions when APP_DEBUG is off. With debug on, Laravel shows its own exception page instead.
It asks the user to try again and links to the IT Service Desk. The rest depends on the environment and on Sentry:
- Error ID. When Sentry captured the exception, the page shows Sentry’s event ID, so a user can quote it in a report.
- Help Us Fix This. With an event ID, the page also shows a form for the user’s name, email and a description. It sends the report to Sentry with
captureFeedback, linked to the event. Name and email are filled in for signed-in users. See Sentry. - Technical Details. The exception message and stack trace show to everyone outside production, so testers without Sentry access can describe failures. In production they show only to users with the
ManageAllpermission.
The user and permission lookups are wrapped in rescue(): if the database is down, the page renders without them and hides the technical details in production.
The Database-Paused Page
Section titled “The Database-Paused Page”Non-production environments on Aurora Serverless v2 can scale the database to zero. The first request after a pause can time out while the database wakes up. bootstrap/app.php uses chassis’s DatabasePausedDetector to recognize that PostgreSQL connection timeout and renders errors.database-paused with status 500 in place of the 500 page.
The page names the environment (APP_ENV), explains that its database is starting, and reloads itself after 30 seconds. Outside production these timeouts aren’t reported to Sentry.
External Service Outages
Section titled “External Service Outages”App\Domains\Core\Exceptions\ServiceDownError is thrown when a service the application depends on is unavailable. The starter throws it when Directory Search can’t provide a user’s details during single sign-on, after retrying.
It renders the 503 page instead of the 500 page, because the fault is in another service. API and JSON requests get a Problem Details 503 response with Retry-After: 60. The error is still reported. To name another service in the message, add a case to App\Domains\Core\Enums\ExternalService.