laravel/framework · error · ClassMorphViolationException
No morph map defined for model
Error message
No morph map defined for model [{$class}]. What it means
Thrown as ClassMorphViolationException (message: 'No morph map defined for model [{$class}].') by getMorphClass() when Relation::requiresMorphMap() is true and the current model class is not registered in the morph map. Morph maps alias model classes to short keys stored in polymorphic morph_type columns; if morph maps are required and the model has no alias, Laravel refuses to write a raw FQCN into the morph map and throws instead.
Solutions
- Register the model in the morph map: Relation::morphMap(['alias' => App\Models\Tag::class]) (typically in AppServiceProvider boot()).
- Disable the requirement if raw class names are acceptable: Relation::requireMorphMap(false).
- Ensure every model participating in morphTo/morphMany relations has an alias when requireMorphMap() is on.
- If renaming a model, update both the morph map alias target and migrate existing morph_type column values.
Example fix
// before
Relation::requireMorphMap();
// Tag not registered -> ClassMorphViolationException when used in morphTo
// after
// in AppServiceProvider::boot()
Relation::morphMap([
'tag' => App\Models\Tag::class,
]); Defensive patterns
Strategy: validation
Validate before calling
use Illuminate\Database\Eloquent\Relations\Relation;
$models = [App\Models\Tag::class, App\Models\Post::class];
$registered = Relation::morphMap();
foreach ($models as $class) {
if (Relation::requiresMorphMap() && ! in_array($class, $registered, true)) {
throw new \LogicException("{$class} has no morph map alias; register it via Relation::morphMap().");
}
} Type guard
function modelHasMorphMap(string $class): bool
{
return in_array($class, \Illuminate\Database\Eloquent\Relations\Relation::morphMap(), true);
} Prevention
- Register every polymorphic model in Relation::morphMap() before enabling requireMorphMap().
- When renaming a model, update the morph map target and migrate morph_type values in the same change.
- Add a boot test asserting all polymorphic models are present in the morph map.
When it happens
Trigger: Enforcing morph maps via Relation::requireMorphMap() and then creating/reading a polymorphic relation involving a model that was never registered with Relation::morphMap([...]). getMorphClass() is invoked when serializing morph types (saving a morphTo / morphMany, building morph type constraints, queueing, etc.).
Common situations: Adding a new model to a polymorphic system after enabling requireMorphMap() without extending the morphMap() call; refactoring model namespaces without updating the morph map aliases; third-party packages that define their own models but are not added to the app's morph map.
Related errors
- Call to undefined cast
- Collection given to whereMorphedTo method may not be empty.
- Collection given to whereNotMorphedTo method may not be…
- Could not verify the hashed value's configuration.
- Expected class to implement guessResourceName method. Make…
AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11).
Data as JSON: /api/errors/0a44a1dec9401c7a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php:1038
*
* @return string
*
* @throws \Illuminate\Database\ClassMorphViolationException
*/
public function getMorphClass()
{
$morphMap = Relation::morphMap();
if (! empty($morphMap) && in_array(static::class, $morphMap)) {
return array_search(static::class, $morphMap, true);
}
if (static::class === Pivot::class) {
return static::class;
}
if (Relation::requiresMorphMap()) {
throw new ClassMorphViolationException($this);
}
return static::class;
}
/**
* Create a new model instance for a related model.
*
* @template TRelatedModel of \Illuminate\Database\Eloquent\Model
*
* @param class-string<TRelatedModel> $class
* @return TRelatedModel
*/
protected function newRelatedInstance($class)
{
return tap(new $class, function ($instance) {
if (! $instance->getConnectionName()) {
$instance->setConnection($this->getConnectionName());View on GitHub (pinned to e0f6eb3518)