All posts

Laravel Error Handling Patterns

Master Laravel error handling with custom exceptions, the Handler class, renderable exceptions, and API error response formatting.

Laravel Error Handling Patterns

Laravel provides a sophisticated exception handling system. Here's how to use it effectively in production.

Custom Exception Classes

class OrderNotFoundException extends Exception
{
    public function __construct(string $orderId)
    {
        parent::__construct("Order {$orderId} not found");
    }

    public function render($request)
    {
        if ($request->expectsJson()) {
            return response()->json([
                'error' => 'order_not_found',
                'message' => $this->getMessage(),
            ], 404);
        }
        return response()->view('errors.order-not-found', [], 404);
    }
}

Laravel automatically calls render() on exceptions that define it.

Configure the Exception Handler

// app/Exceptions/Handler.php
class Handler extends ExceptionHandler
{
    protected $dontReport = [
        AuthorizationException::class,
        ValidationException::class,
    ];

    public function register(): void
    {
        $this->reportable(function (ExternalServiceException $e) {
            // Send to error tracking
            Log::channel('external')->error($e->getMessage(), [
                'service' => $e->getServiceName(),
                'response_code' => $e->getResponseCode(),
            ]);
        });

        $this->renderable(function (ApiException $e, $request) {
            return response()->json([
                'error' => $e->getErrorCode(),
                'message' => $e->getMessage(),
            ], $e->getStatusCode());
        });
    }
}

Validation Error Handling

public function store(Request $request)
{
    $validated = $request->validate([
        'email' => 'required|email|unique:users',
        'name' => 'required|min:2|max:255',
    ]);

    // Laravel automatically returns 422 with error details
    // for API requests and redirects back for web requests
}

Transaction Safety

DB::transaction(function () use ($order) {
    $order->process();
    $order->payment()->charge();
    // If either fails, both roll back
});

Key Patterns

  • Use renderable exceptions — keep error responses close to the exception definition
  • Don't catch exceptions just to re-throw — let them bubble to the handler
  • Use `report()` for side effects — notifications, logging to external services
  • Return consistent API error shapes — always include error code and message

Connect Bugsly to Laravel's exception handler to get real-time visibility into production errors with full request context, user information, and stack traces.

Try Bugsly Free

AI-powered error tracking that explains your bugs. Set up in 2 minutes, free forever for small projects.

Get Started Free