Custom error pages 500.blade.php and 404.blade.php in Laravel
Content Index
- Why customize error pages in Laravel?
- Where and how Laravel manages error pages
- How to create custom error pages in Laravel
- Correct structure of resources/views/errors
- Custom 404 Page Example in Laravel
- Custom 500 Page Example in Laravel
- Summary
- Other error codes (401, 403, 405…)
- What happens with debug and production mode in Laravel
- Best practices for error pages (UX and maintenance)
- How to test your error pages in Laravel
- ❓ Frequently Asked Questions about custom errors in Laravel
- Conclusion
When you start working with Laravel and already have your project running (routes, controllers, even Vue if you use it on the frontend), there is a detail that usually gets left for last… until the first 404 appears in production: error pages.
In my case, at first, I used to leave the default Laravel pages. They worked, yes, but they completely broke the user experience and didn't fit the project's design. Luckily, Laravel makes it very easy to customize error pages and have full control over what the user sees when something goes wrong.
In this article, I explain how to create customized error pages in Laravel, from the basics to real-world best practices for production.
Since we already know how to configure Vue and Laravel, let's move to the next step.
Why customize error pages in Laravel?
Laravel provides decent default error pages for development, but in production:
- They show a generic design
- They don't follow your application's layout
- They don't help the user continue browsing
- They can give an unprofessional image
Customizing these pages allows you to:
- Maintain visual consistency
- Improve the user experience
- Avoid showing sensitive technical information
- Guide the user (go back home, contact, etc.)
And the best part: you don't need to touch routes or controllers for most cases.
Where and how Laravel manages error pages
In Laravel, we can easily customize error pages, such as 404 or 500 types, by creating the corresponding views in the folder:
resources/views/errors/
The name of the view must match the HTTP status code. For example:
resources/views/errors/404.blade.php
resources/views/errors/500.blade.php
The logic is very simple:
- The file name must match the HTTP status code
- If the file exists, Laravel renders it automatically
- No further configuration is necessary
For example:
- 404.blade.php → 404 Error
- 500.blade.php → 500 Error
- 403.blade.php → Access Forbidden
Create the right file and Laravel does all the work.
How to create custom error pages in Laravel
Correct structure of resources/views/errors
If it doesn't exist, create the folder:
resources/views/errors/
Inside, add the files according to the error you want to customize.
⚠️ If the view exists but is empty, Laravel may show a blank page. Always make sure to have content.
Custom 404 Page Example in Laravel
File: resources/views/errors/404.blade.php
@extends('layouts.app') @section('content') <div class="container"> <h1>404 Not Found</h1> <p>Sorry, the page you are looking for does not exist.</p> </div> @endsectionI usually always add a clear link to return home, because a 404 with no way out is a bad experience.
Custom 500 Page Example in Laravel
File: resources/views/errors/500.blade.php
@extends('layouts.app') @section('content') <div class="error-page"> <h1>500 Internal Server Error</h1> <p>Please try again later.</p> <a href="{{ url('/') }}">Go back to the home page</a> </div> @endsectionThe 500 page will only be shown when APP_DEBUG=false.
This confused me quite a bit at first, because in local development I never saw my custom view.
Summary
- We can customize 400x error pages (such as 401, 402, 403, 404, 405) and 500x.
- Customization is done by creating the resources/views/errors folder and the corresponding files with the status code.
- Just by creating the file, Laravel will display that view when the error occurs.
- It is important to add content to the view; otherwise, it may appear blank. You can include styles, components, or any design you want.
- To see the 500 error page, you must ensure that Laravel is in production mode.
- To customize other error codes, simply create files like 401.blade.php, 403.blade.php, etc.
- With this, you will have total control over the appearance of your error pages, avoiding Laravel's default format and improving the user experience.
Other error codes (401, 403, 405…)
You can customize any HTTP code simply by creating the corresponding file:
- 401.blade.php → Unauthorized
- 403.blade.php → Forbidden
- 405.blade.php → Method Not Allowed
Example of 403:
@extends('layouts.app') @section('content') <div class="container text-center"> <h1>403 - Access Denied</h1> <p>You do not have permissions to access this section.</p> </div> @endsectionIn applications with roles and permissions, this file becomes essential.
What happens with debug and production mode in Laravel
This point is key and is usually the cause of 90% of "it doesn't work" cases.
Laravel controls this with the variable:
APP_DEBUGIn development:
APP_DEBUG=true- Laravel shows its detailed error page
- Stack trace, exceptions, files, lines
- Your custom pages are not shown
In production:
APP_DEBUG=false- Laravel hides technical information
- Your views in resources/views/errors are shown
- Correct and secure behavior
I usually test error pages by temporarily disabling debug in local, just to verify the design.
Best practices for error pages (UX and maintenance)
Over time I have learned that a good error page should:
- Use the same layout as the rest of the site
- Explain the problem in human language
- Offer a clear action (go back, reload, contact)
- Not blame the user
Some useful ideas:
- Link to home
- Back button
- Different messages according to the error
- Soft illustrations or icons
Laravel sets no limits here: you can use Blade, components, Tailwind, Bootstrap, or whatever you already use in your project.
How to test your error pages in Laravel
The fastest way is using abort() in a test route:
Route::get('/test-404', function () { abort(404); }); Route::get('/test-500', function () { abort(500); });This way you can visually check that everything works without breaking anything in production.
❓ Frequently Asked Questions about custom errors in Laravel
- Does Laravel automatically detect error pages?
- Yes. If the file exists in resources/views/errors, Laravel renders it without extra configuration.
- Can I create a generic page for multiple errors?
- Yes. You can use:
- 4xx.blade.php for client errors
- 5xx.blade.php for server errors
- Yes. You can use:
- Is it mandatory to touch Handler.php?
- No. It is only necessary in advanced cases where you want custom logic before rendering the view.
- Why do I see the default page and not mine?
- It is almost always because APP_DEBUG=true.
Conclusion
Customizing error pages in Laravel is one of those small improvements that have a huge impact on the quality of an application. Just by creating the right files in resources/views/errors, you can fully control how errors are displayed and offer a much more professional experience.
Spending a few minutes on these pages prevents confusion, improves the project's perception, and saves you unnecessary explanations to users.
Once this is done, you can move on to more advanced topics… like working with polymorphic relations in Laravel, which is usually the next big step.
I agree to receive announcements of interest about this Blog.
Learn how to create custom error pages in Laravel (404, 500, and more). Improve UX, use Blade, and manage errors in production.