laravel/framework · error · InvalidArgumentException

Collection given to whereNotMorphedTo method may not be empt

Error message

Collection given to whereNotMorphedTo method may not be empty.

What it means

whereNotMorphedTo() mirrors whereMorphedTo() with a NOT constraint. An empty model collection cannot define what to exclude, so it raises InvalidArgumentException to avoid generating a no-op (always-true) query that would silently return everything.

Source

Thrown at src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php:687

            $relation = $this->getRelationWithoutConstraints($relation);
        }

        if (is_string($model)) {
            $morphMap = Relation::morphMap();

            if (! empty($morphMap) && in_array($model, $morphMap)) {
                $model = array_search($model, $morphMap, true);
            }

            return $this->whereNot(fn ($query) => $query->whereNullSafeEquals(
                $relation->qualifyColumn($relation->getMorphType()), $model
            ), null, null, $boolean);
        }

        $models = BaseCollection::wrap($model);

        if ($models->isEmpty()) {
            throw new InvalidArgumentException('Collection given to whereNotMorphedTo method may not be empty.');
        }

        return $this->whereNot(function ($query) use ($relation, $models) {
            $models->groupBy(fn ($model) => $model->getMorphClass())->each(function ($models) use ($query, $relation) {
                $query->orWhere(function ($query) use ($relation, $models) {
                    $query->whereNullSafeEquals($relation->qualifyColumn($relation->getMorphType()), $models->first()->getMorphClass())
                        ->whereIn($relation->qualifyColumn($relation->getForeignKeyName()), $models->map->getKey());
                });
            });
        }, null, null, $boolean);
    }

    /**
     * Add a morph-to relationship condition to the query with an "or where" clause.
     *
     * @param  \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string  $relation
     * @param  \Illuminate\Database\Eloquent\Model|iterable<int, \Illuminate\Database\Eloquent\Model>|string|null  $model
     * @return $this

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Skip the clause when empty: if ($exclude->isNotEmpty()) { $query->whereNotMorphedTo(...); }.
  2. If exclusion of 'nothing' should be a no-op, structure the builder conditionally rather than passing empty.
  3. Validate request inputs upstream so empty exclude lists never reach the query layer.

Example fix

// before
$query->whereNotMorphedTo('commentable', $excludedModels); // may be empty

// after
if ($excludedModels->isNotEmpty()) {
    $query->whereNotMorphedTo('commentable', $excludedModels);
}
Defensive patterns

Strategy: validation

Validate before calling

$models = \Illuminate\Support\Collection::wrap($model);
if ($models->isEmpty()) {
    // exclusion of nothing -> no clause needed
    return $query;
}
return $query->whereNotMorphedTo($relation, $models);

Type guard

function hasExcludableMorphModels(mixed $model): bool
{
    return ! \Illuminate\Support\Collection::wrap($model)->isEmpty();
}

Try / catch

try {
    return $query->whereNotMorphedTo($relation, $models);
} catch (\InvalidArgumentException $e) {
    if (str_contains($e->getMessage(), 'may not be empty')) {
        return $query;
    }
    throw $e;
}

Prevention

When it happens

Trigger: Calling $query->whereNotMorphedTo('commentable', collect([])) (or an empty iterable), e.g. when excluding items from a user filter that came back empty.

Common situations: Optional 'exclude' filter that resolved to no IDs; empty result from a sub-query feeding whereNotMorphedTo; defensive code path that forgot to short-circuit on empty input.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/f76189c4e80c81e8.json. Report an issue: GitHub.