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

Every exception lives in RoundlyConsulting\Attributes\Exceptions and extends AttributesException, so one catch covers them all:

ExceptionThrown whenCarries
UnknownAttributeExceptionStrict mode is on and a value or meta write names an attribute with neither a global nor a model-schema definition.—
InvalidAttributeValueExceptionA value fails its definition’s type or rules, or cannot be encoded to its type.attributeName, messages(), errorBag()
DuplicateAttributeValueExceptionA unique definition’s value is already held by another owner — caught before the write, or by the unique index when two writers race.attributeName, scope
MissingRequiredAttributeExceptionvalidateAttributes() finds a required attribute absent.attributeName
AttributesExceptionBase class of all four (extends RuntimeException).—

Misconfiguration — an invalid config value or definition — throws the toolkit’s RoundlyConsulting\PackageToolkit\Exceptions\InvalidConfigurationException instead, which is not an AttributesException. Its message names the offending key.

Friendly validation errors

InvalidAttributeValueException carries the failing attribute name and the full validator bag. messages() prefixes each message with the attribute name:

use RoundlyConsulting\Attributes\Exceptions\AttributesException;
use RoundlyConsulting\Attributes\Facades\Attributes;
use RoundlyConsulting\Attributes\Exceptions\InvalidAttributeValueException;

try {
    Attributes::for($product)->set('rating', 9);
} catch (InvalidAttributeValueException $e) {
    $e->attributeName; // 'rating'
    $e->messages();    // ['rating: The rating field must not be greater than 5.']
    $e->errorBag();    // Illuminate\Support\MessageBag|null
} catch (AttributesException $e) {
    report($e);        // unknown, duplicate or missing-required attribute
}

When a value cannot be encoded to its type at all, the exception has no validator bag — errorBag() returns null and messages() an empty list; getMessage() explains the reason.

Returning a validation response

Rethrow as Laravel’s ValidationException to get the usual 422 response or redirect with errors:

use Illuminate\Validation\ValidationException;
use RoundlyConsulting\Attributes\Exceptions\InvalidAttributeValueException;
use RoundlyConsulting\Attributes\Facades\Attributes;

try {
    Attributes::for($product)->stage()
        ->set('rating', $request->integer('rating'))
        ->save();
} catch (InvalidAttributeValueException $e) {
    throw ValidationException::withMessages([
        (string) $e->attributeName => $e->errorBag()?->all() ?? [$e->getMessage()],
    ]);
}

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.