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

Track up to 100 issues per month on the free plan, with unlimited events and no credit card required.

Get Started Free