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

  1. Register the model in the morph map: Relation::morphMap(['alias' => App\Models\Tag::class]) (typically in AppServiceProvider boot()).
  2. Disable the requirement if raw class names are acceptable: Relation::requireMorphMap(false).
  3. Ensure every model participating in morphTo/morphMany relations has an alias when requireMorphMap() is on.
  4. 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

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


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)