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
- Split the collection by class with groupBy(get_class($model)) and dispatch one job per type.
- Eager-load / build separate collections so each queued payload contains a single model type.
- If queueing is accidental, call the job synchronously (sync queue) or convert the data to a primitive array before queueing.
- 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
- Never concat()/merge() different model types into a collection you intend to queue.
- When queueing, group by get_class() first and dispatch per type.
- Add a test that the collection handed to a job contains exactly one model class.
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
- Queueing collections with multiple model connections is not…
- Queueable entity [ ] not found for ID [ ].
- The provided class must extend…
- The provided class must extend…
- Unable to create query for collection with mixed types.
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)