When you create a new Laravel project, error and exception handling is already configured. You customize it through the withExceptions method in bootstrap/app.php:
// bootstrap/app.phpuse Illuminate\Foundation\Application;use Illuminate\Foundation\Configuration\Exceptions;return Application::configure(basePath: dirname(__DIR__)) ->withExceptions(function (Exceptions $exceptions): void { // Configure exception reporting and rendering here })->create();
The $exceptions object passed to the closure is an instance of Illuminate\Foundation\Configuration\Exceptions and manages all exception handling for your application.
Reporting means logging exceptions or sending them to an external service like Sentry or Flare. By default, exceptions are logged according to your config/logging.php configuration.
Report an exception without interrupting the current request:
public function isValid(string $value): bool{ try { // Validate the value... } catch (Throwable $e) { report($e); return false; }}
The report helper is useful for background jobs and non-critical operations where you want to record the error without returning an error page to the user.
Calling report multiple times with the same exception instance can create duplicate log entries. Use dontReportDuplicates to ensure each instance is reported only once:
Define a context() method on an exception class to include data specific to that exception:
<?phpnamespace App\Exceptions;use Exception;class InvalidOrderException extends Exception{ public function __construct( private readonly int $orderId, string $message = '', ) { parent::__construct($message); } /** * Get context information for this exception. * * @return array<string, mixed> */ public function context(): array { return ['order_id' => $this->orderId]; }}
Create exception classes in app/Exceptions/. Define report() and render() methods directly on the class instead of in bootstrap/app.php — Laravel calls them automatically.
1
Generate the exception class
php artisan make:exception InvalidOrderException
2
Implement report() and render()
<?phpnamespace App\Exceptions;use Exception;use Illuminate\Http\Request;use Illuminate\Http\Response;class InvalidOrderException extends Exception{ public function __construct( private readonly int $orderId, string $message = 'Invalid order.', ) { parent::__construct($message); } /** * Report the exception. */ public function report(): void { // Notify an external service, etc. } /** * Render the exception as an HTTP response. */ public function render(Request $request): Response { return response()->view('errors.invalid-order', [ 'orderId' => $this->orderId, ], 422); }}
You can type-hint dependencies in the report() method and Laravel’s service container will inject them automatically.
// Abort when the condition is trueabort_if(! $user->isAdmin(), 403);// Abort when the condition is falseabort_unless($user->hasPermission('edit'), 403, 'Permission denied.');
These helpers are useful for authorization checks in controllers and middleware, often alongside gates and policies.
Fallback pages do not apply to 404, 500, and 503 responses — Laravel has dedicated internal pages for those. Create individual files such as 404.blade.php to customize them.