theaaronlawrence / culprit-php
Report exceptions from your Laravel app to Culprit.
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.8.2 || ^8.0
- laravel/framework: ^12.0|^13.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.27
- orchestra/testbench: ^10.0|^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Report exceptions from your Laravel 12 or 13 app to Culprit.
This package used to be called theaaronlawrence/laravel-culprit. To move, run composer remove theaaronlawrence/laravel-culprit && composer require theaaronlawrence/culprit-php; nothing else changes.
Installation
-
Install the package:
composer require theaaronlawrence/culprit-php
-
Add
Culprit::handles($exceptions);insidewithExceptionsinbootstrap/app.php:use TheAaronLawrence\Culprit\Facades\Culprit; ->withExceptions(function (Exceptions $exceptions): void { Culprit::handles($exceptions); })
Laravel still logs exceptions as usual.
-
Add your project's key to
.env:CULPRIT_KEY=your-project-key
-
Run
php artisan culprit:testand see the error arrive in Culprit.
With no CULPRIT_KEY, nothing is reported and no HTTP calls are made.
Older app structure
Apps upgraded from before Laravel 11 may still have app/Exceptions/Handler.php and app/Http/Kernel.php. They have no withExceptions.
In Handler::register(), call handles() with a new Exceptions object:
use Illuminate\Foundation\Configuration\Exceptions; use TheAaronLawrence\Culprit\Facades\Culprit; public function register(): void { Culprit::handles(new Exceptions($this)); }
HTTP errors are sent after the response, using deferred callbacks. Check that \Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks::class is in the global $middleware list in app/Http/Kernel.php. Add it if it is missing. Without it, HTTP errors are never sent, even though culprit:test works.
Configuration
Publish the config file with php artisan vendor:publish --tag=culprit-config if you need to change the redaction lists.
| Env key | Default | What it does |
|---|---|---|
CULPRIT_KEY |
none | The project key, sent as a bearer token. Required: nothing is sent without it. |
CULPRIT_SEND_IP |
false |
Send the client IP address with HTTP context. |
CULPRIT_SEND_USER_DETAILS |
false |
Send the authenticated user's name and email (the ID is always sent). |
CULPRIT_STRIP_QUERY_BINDINGS |
true |
Remove bound values from QueryException messages. |
CULPRIT_VENDOR_SOURCE |
false |
Send source snippets for vendor frames as well as your own code. |
How it behaves
Reporting never breaks your app: every failure is swallowed, HTTP requests are sent after the response has gone out, the same error is sent once per 10 seconds, and 413 and 429 responses pause sending.
Every report carries an X-Culprit-Report header, and an error raised while handling a request with that header is never reported. That lets a Culprit tracker report its own errors without looping when its ingest endpoint fails.
License
MIT.