Muhammad Yasir Amin

Loading websiteโ€ฆ

More from Muhammad Yasir Amin

Build Along With Me

Practical walkthroughs on Laravel, React, APIs and deployment workflows.

Subscribe on YouTube

Laravel 13 Custom Error Pages: Create 404, 500 and Other HTTP Error Views

๐Ÿ› ๏ธ Laravel Tutorials4 min read

Laravel 13 Custom Error Pages: Create 404, 500 and Other HTTP Error Views

Muhammad Yasir Amin

Muhammad Yasir Amin

Senior Full Stack Engineerโ€ขNov 9, 2026
Laravel 13 Custom Error Pages: Create 404, 500 and Other HTTP Error Views

To create a custom error page in Laravel 13, add a Blade file named after the HTTP status code in resources/views/errors, such as 404.blade.php or 500.blade.php. Laravel renders that view automatically whenever the matching error happens.

You can also publish the default templates, add fallback pages for whole ranges like 4xx and 5xx, and return JSON for API routes. This guide covers each step.

What do I need first?

  • Laravel 13 (current stable at the time of writing) on a supported PHP version.
  • APP_DEBUG=false to see your custom pages. When debug is on, Laravel shows its detailed error screen for exceptions instead.

How do I create a custom 404 page?

Create the file resources/views/errors/404.blade.php.

TypeScript
@extends('layouts.app')

@section('content')
    <div class="text-center">
        <h1>404</h1>
        <p>Sorry, we could not find that page.</p>
        <a href="{{ url('/') }}">Back to the home page</a>
    </div>
@endsection

Replace layouts.app with your own layout. If your layout needs data from a controller or a view composer that may fail, use a plain HTML page for error views, because an error inside the error page makes things worse.

How do I show the exception message?

The HttpException raised by abort() is passed to the view as $exception.

Shell
{{-- resources/views/errors/403.blade.php --}}
<h1>403</h1>
<p>{{ $exception->getMessage() ?: 'You are not allowed to view this page.' }}</p>
Code
abort(403, 'This report is only for administrators.');

Show messages only for errors you wrote on purpose. Never print internal exception text from unexpected failures such as 500 errors.

Which status codes should I customize?

  • 404 page not found
  • 403 forbidden
  • 419 page expired (a missing or expired CSRF token)
  • 429 too many requests
  • 500 server error
  • 503 maintenance mode or service unavailable

How do I use the default templates as a starting point?

Code
php artisan vendor:publish --tag=laravel-errors

This copies Laravel's built-in error views into resources/views/errors. Edit them to match your brand.

How do I add fallback pages?

Create 4xx.blade.php and 5xx.blade.php in the same folder. Laravel uses them when no file exists for the exact code. They do not replace the dedicated pages for 401, 402, 403, 404, 419, 429, 500 and 503, so create those individually if you want to change them.

How do I return JSON for API routes?

Laravel renders JSON automatically when the client sends an Accept: application/json header. To force a custom body for a specific exception, use bootstrap/app.php.

JavaScript
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

->withExceptions(function (Exceptions $exceptions): void {
    $exceptions->render(function (NotFoundHttpException $e, Request $request) {
        if ($request->is('api/*')) {
            return response()->json(['message' => 'Record not found.'], 404);
        }
    });
})

If the closure returns nothing, Laravel falls back to its default rendering, so web routes still use your Blade 404 page.

How do I make a custom exception render its own page?

JavaScript
namespace App\Exceptions;

use Exception;
use Illuminate\Http\Request;

class PaymentFailedException extends Exception
{
    public function render(Request $request)
    {
        return response()->view('errors.payment-failed', [], 402);
    }
}

Throw it anywhere with throw new PaymentFailedException();. Laravel calls the render() method on the exception itself.

What are the common mistakes?

  • Debug mode left on. You see the debug screen, not your page. Set APP_DEBUG=false to test.
  • Wrong file name or folder. It must be resources/views/errors/404.blade.php.
  • Cached views. Run php artisan view:clear after edits on a server.
  • Heavy layouts. If the layout queries the database and the database is down, the 500 page also fails. Keep error views simple.
  • Using 4xx.blade.php for 404. Dedicated codes need dedicated files.

How do I test the pages?

JavaScript
public function test_unknown_page_shows_custom_404(): void
{
    $this->get('/this-page-does-not-exist')
        ->assertNotFound()
        ->assertSee('could not find that page');
}

To check a 500 page by hand, add a temporary route that throws an exception, load it with APP_DEBUG=false locally, then remove the route.

FAQ

Why do I still see Laravel's default 404?

Usually the file name is wrong or view caches are stale. Check the path and run php artisan view:clear.

Can I use a Blade component in error pages?

Yes, but keep it free of database calls. Error pages should render even when parts of the app are broken.

How do I change the maintenance mode page?

Create resources/views/errors/503.blade.php. Laravel uses it when the application is down.

References

Article Index & Topic Tags
LaravelBladeError-HandlingRouting

YouTube Channel

Build Along With Me

Practical walkthroughs on Laravel, React, APIs and deployment workflows.

Muhammad Yasir Amin
Available for Contracts
Author & Solutions Architect

Senior Full Stack Engineer

Independent Senior Full Stack Engineer working on Laravel, React and Next.js applications, APIs and delivery workflows.

Laravel & PHP ApplicationsReact & Next.js InterfacesREST APIs & IntegrationsDatabase Queries & DebuggingDocker Development WorkflowsClear Scope & Handover
Discuss Your Next Step

What Does Your Application Need Next?

Share your current system, the problem you want to solve and what a useful result looks like. We can identify the right starting point and agree on a practical scope.

Technical Audit

Find the Next Useful Fix

Application Development

Scoped, Reviewable Milestones

Ongoing Support

Agreed Capacity and Priorities

Share your goals, current stack and requirements before the call.