Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Error Mailer Laravel Package

hugomyb/filament-error-mailer

Filament Error Mailer automatically emails you when errors occur in your Filament admin panel, including useful exception details so you can spot and fix issues faster. A simple monitoring add-on for Laravel and Filament apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish

composer require hugomyb/filament-error-mailer
php artisan vendor:publish --tag="filament-error-mailer-config"

The publish tag and config filename are the first things to confirm against the README — small packages like this rename tags between minor versions. If the tag fails, php artisan vendor:publish with the interactive prompt will list what's actually available.

Register the plugin in the panel provider that should own the settings UI:

// app/Providers/Filament/AdminPanelProvider.php
public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->plugin(\Hugomyb\FilamentErrorMailer\FilamentErrorMailerPlugin::make());
}

Configure the alert path. Before touching the plugin config, verify raw mail works from the app: set MAIL_* in .env, then php artisan tinker and Mail::raw('test', fn ($m) => $m->to('[email protected]')->subject('test'));. Error mailers fail silently and confusingly when the underlying mailer is misconfigured, and you'll blame the plugin for a transport problem.

Where to look first, in order:

  1. The published config/filament-error-mailer.php — recipients, enable/disable, threshold, throttling are almost always here.
  2. vendor/hugomyb/filament-error-mailer/src/ — it's a small package; read the whole src/ tree in ten minutes. You need to know exactly which hook it uses (log listener vs. exception handler) because that determines what it does and does not catch.
  3. The plugin class itself, to see whether it registers a settings page, a navigation item, or only a service provider binding.

First use case: production Filament admin panels where a 500 in a resource page currently goes unnoticed until a user complains. The plugin turns that into an email to the on-call developer with the exception, URL, and (usually) a stack trace. It is not a replacement for Sentry/Flare/Bugsnag — it's a "someone should look at this now" ping for small teams that don't want another SaaS bill.

Minimal viable setup:

// config/filament-error-mailer.php
'enabled'     => env('ERROR_MAILER_ENABLED', app()->isProduction()),
'recipients'  => array_filter(explode(',', env('ERROR_MAILER_TO', ''))),
ERROR_MAILER_ENABLED=true
[email protected],[email protected]

Implementation Patterns

Gate hard by environment. The single most valuable line of config is the enable flag tied to app()->isProduction(). Local development generates exceptions constantly (validation aborts, 404s, Livewire hydration noise); without gating you will burn through your mail quota and start ignoring the alerts within a day.

'enabled' => env('ERROR_MAILER_ENABLED', false),

Then opt in per environment in .env rather than opting out — default-closed is safer for a package with this little scrutiny.

Queue the send. If the package sends synchronously, the email happens inside the failing request's lifecycle: your user waits for SMTP while staring at a 500. Either the config exposes a queue option or you override the Mailable with implements ShouldQueue. Confirm a worker is actually running — a queued error mailer with a dead queue:work is worse than no mailer, because you'll believe you have monitoring.

Throttle and deduplicate. A broken database connection or a missing column produces the same exception on every request. Without throttling, a five-minute outage generates thousands of emails, your provider rate-limits you, and the real signal is lost. Look for a throttle / rate_limit / cache_ttl key and set it explicitly; if the package lacks one, wrap the notification in your own RateLimiter or Cache::lock() around the exception hook. Key on a hash of exception class + file + line, not the message (messages contain variable data like IDs).

Use a dedicated recipient list, not a personal inbox. oncall@ or a group alias survives staff turnover and lets you route through your provider's escalation rules.

Keep it in the "second responder" slot. Pair it with Laravel's own withExceptions() reporting so you retain structured logs:

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->report(function (Throwable $e) {
        // your existing reporting (Sentry, Slack, log channel)
    });
})

The plugin should add a channel, not replace one. If it hooks into the exception handler and you also register a custom handler, verify ordering — a return false or an early report() in your handler can suppress the package's hook entirely.

Multiple panels. The error interception is (typically) global, not per-panel, even though the plugin registers per-panel. Registering it in one panel provider is usually enough; registering it in four may double-send if the listener binds per panel. Test with a deliberate exception before assuming.

Customize the email. Most plugins of this shape publish a Blade view for the mailable. Publish it and add what you actually need in triage: the authenticated user's ID, the panel, the request payload (redacted), and a link to your log viewer. A stock stack trace alone rarely tells you whether it's one user or all of them.

Testing pattern:

Mail::fake();
$this->withoutExceptionHandling();

// deliberately trigger the caught condition

Use Mail::assertSent(ErrorMailerMailable::class) to prove the wiring, then re-enable normal handling. Also add the plugin to your testing env disable list so unrelated feature tests don't accumulate outbound mail.

Staged rollout. Enable it in staging first, point it at yourself, and let a week of real traffic tell you whether the volume is tolerable before production.


Gotchas and Tips

This package is barely adopted — treat it as code you own. Twelve stars, zero dependents. That is not disqualifying for a small utility, but it means: pin an exact version ("hugomyb/filament-error-mailer": "1.2.3"), read src/ before deploying, and be prepared to fork. There is no community to catch a regression, and a security advisory would likely go unnoticed.

Check Filament major-version compatibility explicitly. Filament v3 → v4 involved breaking changes in plugin contracts, asset registration, and the panel API. A release dated 2026-09-08 does not guarantee it supports the Filament version in your composer.json. Check the package's own composer.json constraint on filament/filament before assuming, and run composer why-not if resolution fails.

Config cache. After editing the config file, php artisan config:clear. In production, config:cache is standard and stale config is the most common reason "the recipients are set but no email arrives."

Sensitive data leaves your server. Stack traces contain file paths, SQL fragments, and sometimes bound parameters — which means user emails, tokens, or password hashes can land in an inbox and in your mail provider's retention. Turn off query-binding dumps if the package offers the option, and prefer a recipient address inside your own domain.

Mail storms and self-inflicted loops. If the mail transport itself is the failing component (misconfigured SMTP, expired API key), the error mailer can try to send an email about the mail failure — logging a second error, which triggers another email. Throttle at the cache level and make sure mailer exceptions are excluded from what the plugin catches.

Debugging checklist when no email arrives, in order: is enabled true for this env? does the config contain recipients? does plain Mail::raw() work? is the app throwing something the plugin actually hooks (many only catch ErrorException/Throwable from the handler, not abort(403) or validation failures)? is there a failed_jobs row? Check storage/logs/laravel.log — the plugin's own failures usually log there rather than surfacing.

Synchronous send = slow error pages. Even 200ms of SMTP adds up under a retry storm. If the package has no queue option, subclass the Mailable with ShouldQueue and rebind it.

Extension points worth knowing: the Mailable class (override the view and subject), the recipient/throttle config, and — if present — the notification or listener class bound in the service provider. Because the package is small, $this->app->bind() or $this->app->extend() in your AppServiceProvider is often cleaner than forking.

Consider whether you need it at all. Laravel's LOG_LEVEL=error plus a log-based alert (Papertrail, Better Stack, even a cron that greps laravel.log and mails on match) gives you the same outcome with zero third-party code and no version-coupling to Filament. Reach for this plugin when the appeal is specifically the in-panel configuration UI and you value that convenience over the dependency.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager