laravel/framework · error · ClassMorphViolationException
No morph map defined for model [{$class}].
Error message
No morph map defined for model [{$class}]. What it means
When Relation::requireMorphMap() is enabled, every morphable model must be registered in the morph map before its class name is used as a morph type. getMorphClass() throws ClassMorphViolationException if the model is absent from the map, preventing ambiguous class-name storage across deployments.
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 bd6b5437e6)
Solutions
- Register the model in the morph map, typically in AppServiceProvider::boot(): Relation::morphMap(['alias' => Model::class]).
- Confirm Relation::requireMorphMap() is intended; if not, do not enable it.
- Add a startup test that iterates morphable models and asserts they appear in Relation::morphMap().
Example fix
// before
Relation::requireMorphMap();
// Post is morphable but never registered -> throws on create
// after (in AppServiceProvider::boot)
Relation::morphMap([
'post' => \App\Models\Post::class,
'video' => \App\Models\Video::class,
]); Defensive patterns
Strategy: validation
Validate before calling
use Illuminate\Database\Eloquent\Relations\Relation;
if (Relation::requiresMorphMap()) {
foreach ([\App\Models\Post::class, \App\Models\Video::class] as $m) {
if (! in_array($m, Relation::morphMap(), true)) {
throw new \RuntimeException("Morph map missing for {$m}");
}
}
} Type guard
function isRegisteredInMorphMap(string $modelClass): bool
{
return in_array($modelClass, \Illuminate\Database\Eloquent\Relations\Relation::morphMap(), true);
} Try / catch
try {
return $model->getMorphClass();
} catch (\Illuminate\Database\ClassMorphViolationException $e) {
\Illuminate\Database\Eloquent\Relations\Relation::morphMap([
strtolower(class_basename($e->model)) => $e->model,
]);
return $model->getMorphClass();
} Prevention
- Register morph maps once in AppServiceProvider::boot().
- Add a startup test asserting every morphable model is mapped when requireMorphMap is on.
- Avoid enabling requireMorphMap mid-project without registering all existing morph models.
When it happens
Trigger: Calling Relation::requireMorphMap(); using morphMany/morphTo/morphMap without registering the model via Relation::morphMap(['post' => Post::class]); then triggering any operation that needs the morph alias (creating a polymorphic record, serializing, whereMorphedTo with a model instance).
Common situations: New morphable model added without a morph-map entry; enabling requireMorphMap mid-project; package models not registered; CI/local config drift where morph map is set in AppServiceProvider but skipped in a worker.
Related errors
- Attempted to lazy load [{$relation}] on model [{$class}] but
- %s::%s must return a relationship instance, but "null" was r
- %s::%s must return a relationship instance.
- Could not verify the hashed value's configuration.
- Call to undefined cast [{$castType}] on column [{$column}] i
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/0a44a1dec9401c7a.json.
Report an issue: GitHub.