laravel/framework · error · ValueError
Value [%s] is not of the expected enum type [%s].
Error message
Value [%s] is not of the expected enum type [%s].
What it means
getStorableEnumValue() is invoked when persisting an enum-cast attribute. It requires the value be an instance of the enum class declared in $casts. If a different enum (or any non-matching UnitEnum) is assigned, a ValueError is thrown because the value cannot be safely stored for that column.
Source
Thrown at src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:1333
{
return is_subclass_of($enumClass, BackedEnum::class)
? $enumClass::from($value)
: constant($enumClass.'::'.$value);
}
/**
* Get the storable value from the given enum.
*
* @param string $expectedEnum
* @param \UnitEnum $value
* @return string|int
*
* @throws \ValueError
*/
protected function getStorableEnumValue($expectedEnum, $value)
{
if (! $value instanceof $expectedEnum) {
throw new ValueError(sprintf('Value [%s] is not of the expected enum type [%s].', var_export($value, true), $expectedEnum));
}
return enum_value($value);
}
/**
* Get an array attribute with the given key and value set.
*
* @param string $path
* @param string $key
* @param mixed $value
* @return array
*/
protected function getArrayAttributeWithValue($path, $key, $value)
{
return tap($this->getArrayAttributeByKey($key), function (&$array) use ($path, $value) {
Arr::set($array, str_replace('->', '.', $path), $value);
});View on GitHub (pinned to bd6b5437e6)
Solutions
- Match the enum class exactly: ensure the assigned value is an instance of the cast-target enum.
- Convert via the enum's from()/tryFrom() before assignment: $model->status = AppStatus::from($incoming->value).
- Update $casts to the correct enum class if the contract changed.
Example fix
// before $model->status = OtherStatus::Active; // status cast to AppStatus // after $model->status = AppStatus::from(OtherStatus::Active->value);
Defensive patterns
Strategy: type-guard
Validate before calling
$expected = \App\Enums\AppStatus::class;
if (! $value instanceof $expected) {
$value = $expected::from((string) $value); // or tryFrom with fallback
}
$model->status = $value; Type guard
function isExpectedEnum(mixed $value, string $enumClass): bool
{
return $value instanceof $enumClass;
} Try / catch
try {
$model->status = $value;
} catch (\ValueError $e) {
if (str_contains($e->getMessage(), 'is not of the expected enum type')) {
$model->status = \App\Enums\AppStatus::tryFrom((string) $value) ?? \App\Enums\AppStatus::Default;
} else {
throw $e;
}
} Prevention
- Keep a single source of truth for each enum and reference it via ::class in $casts and callers.
- Use Form Request validation with Enum::when rules to convert input to the right enum before assignment.
- Assert cross-enum assignments are intentional and convert via from()/tryFrom().
When it happens
Trigger: Assigning $model->status = OtherStatus::Active when 'status' is cast to AppStatus; passing a backed-enum of a different type; assigning a UnitEnum where a BackedEnum is expected and the framework cannot extract a scalar.
Common situations: Two similarly-named enums in the codebase; refactor that changed the enum class but left stale data or callers; receiving enum values from an API/form request that maps to the wrong enum; cross-enum assignments in tests.
Related errors
- The provided class must extend [{Collection::class}].
- The provided class must extend [{Collection::class}].
- The cast object for the {$attribute} attribute must implemen
- Unable to create query for collection with mixed types.
- %s::%s must return a relationship instance.
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/e88dfbd7ac5aa9a8.json.
Report an issue: GitHub.