laravel/framework · error · LogicException

Queueing collections with multiple model types is not…

Error message

Queueing collections with multiple model types is not supported.

What it means

Thrown by Eloquent\Collection::getQueueableClass() when the collection contains more than one concrete model type. To serialize a collection for a queued job or queued notification/queued mailable, Laravel needs a single class name to restore on the other side; a mix of types (e.g. User and Post) cannot be represented by one class string. The method iterates every model and compares getQueueableModelClass() against the first.

Solutions

  1. Split the collection by class with groupBy(get_class($model)) and dispatch one job per type.
  2. Eager-load / build separate collections so each queued payload contains a single model type.
  3. If queueing is accidental, call the job synchronously (sync queue) or convert the data to a primitive array before queueing.
  4. Ensure polymorphic relations are resolved to a single concrete type before they enter the queue payload.

Example fix

// before
$collection = $users->concat($posts);
dispatch(new ProcessCollection($collection)); // LogicException

// after
$users->each(fn ($u) => dispatch(new ProcessModel($u)));
$posts->each(fn ($p) => dispatch(new ProcessModel($p)));
Defensive patterns

Strategy: validation

Validate before calling

$types = $collection->map(fn ($m) => get_class($m))->unique();
if ($types->count() > 1) {
    throw new \LogicException('Collection mixes model types: ' . $types->implode(', '));
}
// safe to dispatch
dispatch(new ProcessCollection($collection));

Type guard

function containsSingleModelType(\Illuminate\Support\Collection $c): bool
{
    return $c->map(fn ($m) => get_class($m))->unique()->count() === 1;
}

Try / catch

try {
    dispatch(new ProcessCollection($collection));
} catch (\LogicException $e) {
    if (str_contains($e->getMessage(), 'multiple model types')) {
        $collection->groupBy(fn ($m) => get_class($m))
            ->each(fn ($group) => dispatch(new ProcessCollection($group)));
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Passing a collection that mixes model types into a queued job constructor, a queued notification via ->notify(new X($collection)), or anywhere the collection is serialized onto the queue. Also triggered when a relation collection unexpectedly contains related-but-different result classes (e.g. a polymorphic relation that was materialized into one Eloquent\Collection).

Common situations: Combining two query results with concat()/merge() and dispatching to a job; queueing a polymorphic relationship collection; a custom collection that filters in a base Model instance alongside subclassed models.

Related errors


AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11). Data as JSON: /api/errors/fa847b2575e82765. Report an issue: GitHub.

Appendix: source

Thrown at src/Illuminate/Database/Eloquent/Collection.php:841

    /**
     * Get the type of the entities being queued.
     *
     * @return string|null
     *
     * @throws \LogicException
     */
    public function getQueueableClass()
    {
        if ($this->isEmpty()) {
            return;
        }

        $class = $this->getQueueableModelClass($this->first());

        $this->each(function ($model) use ($class) {
            if ($this->getQueueableModelClass($model) !== $class) {
                throw new LogicException('Queueing collections with multiple model types is not supported.');
            }
        });

        return $class;
    }

    /**
     * Get the queueable class name for the given model.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return string
     */
    protected function getQueueableModelClass($model)
    {
        return method_exists($model, 'getQueueableClassName')
            ? $model->getQueueableClassName()
            : get_class($model);
    }

View on GitHub (pinned to e0f6eb3518)