NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Every domain exception extends NotificationsException (a RuntimeException) and carries a translated message, a stable machine code (errorCode()) and an HTTP status (status()), so a host API maps them without matching message text. Messages name type keys and model basenames, never a PHP class:

use RoundlyConsulting\Notifications\Exceptions\NotificationsException;

try {
    Notifications::preferences($user)->mute('security.alert');
} catch (NotificationsException $e) {
    $e->errorCode();    // 'mandatory_notification'
    $e->status();       // 422
    $e->getMessage();   // translated: The notification "security.alert" is required and cannot be switched off.
}
ExceptionCodeHTTPWhen
UnknownNotificationTypeExceptionunknown_type422A type key nobody registered.
InvalidNotificationTypeExceptioninvalid_type422A type that cannot work, at registration (see Notification types).
DuplicateNotificationTypeExceptionduplicate_type422One key registered twice, naming both sources.
InvalidNotificationSubjectExceptioninvalid_subject422A subject of another class; a subject for a type without one; no subject where one is needed (an escalation).
InvalidNotificationDataExceptioninvalid_data422Data that is not plain JSON (naming the path) or over max_data_bytes; a bad context; an unknown channel.
InvalidRecipientExceptioninvalid_recipient422A recipient that is not an Eloquent model.
UnresolvableRecipientsExceptionunresolvable_recipients422A group that implements no ProvidesNotificationRecipients under the default resolver.
UnstorableRecipientsExceptionunstorable_recipients422A closure (or non-scalar resolver arguments) where recipients must be stored.
NoOwnerExceptionno_owner422Recipients::owner() without a subject, or a subject that names no owner.
MissingAccessCheckExceptionmissing_access_check500The default access check on a subject with neither a policy nor the ability.
MandatoryNotificationExceptionmandatory_notification422A write that would mute a mandatory type.
UnknownNotificationCategoryExceptionunknown_notification_category422A category no registered type uses.
InboxItemNotFoundExceptioninbox_item_not_found404A missing id or another recipient’s item — the same answer.
InvalidQuietHoursExceptioninvalid_quiet_hours422Equal start and end, or a time that is not HH:MM.
InvalidTimezoneExceptioninvalid_timezone422Not an IANA timezone.
InvalidReminderRuleExceptioninvalid_reminder422A rule that cannot work, or an unreadable or non-positive escalation delay.
InvalidInteropMappingExceptioninvalid_interop_mapping500A mapping to an unknown type, or a time-critical class mapped to a type that is not urgent, windowless and non-digestible.

Configuration errors throw InvalidNotificationsConfigurationException (English, naming the key; it extends package-toolkit’s base exception) or the toolkit’s InvalidConfigurationException.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.