{"record":{"id":"fa847b2575e82765","repo":"laravel/framework","slug":"queueing-collections-with-multiple-model-types-is","errorCode":null,"errorMessage":"Queueing collections with multiple model types is not supported.","messagePattern":"Queueing collections with multiple model types is not supported\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Database/Eloquent/Collection.php","lineNumber":841,"sourceCode":"\n    /**\n     * Get the type of the entities being queued.\n     *\n     * @return string|null\n     *\n     * @throws \\LogicException\n     */\n    public function getQueueableClass()\n    {\n        if ($this->isEmpty()) {\n            return;\n        }\n\n        $class = $this->getQueueableModelClass($this->first());\n\n        $this->each(function ($model) use ($class) {\n            if ($this->getQueueableModelClass($model) !== $class) {\n                throw new LogicException('Queueing collections with multiple model types is not supported.');\n            }\n        });\n\n        return $class;\n    }\n\n    /**\n     * Get the queueable class name for the given model.\n     *\n     * @param  \\Illuminate\\Database\\Eloquent\\Model  $model\n     * @return string\n     */\n    protected function getQueueableModelClass($model)\n    {\n        return method_exists($model, 'getQueueableClassName')\n            ? $model->getQueueableClassName()\n            : get_class($model);\n    }","sourceCodeStart":823,"sourceCodeEnd":859,"githubUrl":"https://github.com/laravel/framework/blob/e0f6eb3518ac29fbbca8529e97d0df7fc9f24481/src/Illuminate/Database/Eloquent/Collection.php#L823-L859","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\n$collection = $users->concat($posts);\ndispatch(new ProcessCollection($collection)); // LogicException\n\n// after\n$users->each(fn ($u) => dispatch(new ProcessModel($u)));\n$posts->each(fn ($p) => dispatch(new ProcessModel($p)));","handlingStrategy":"validation","validationCode":"$types = $collection->map(fn ($m) => get_class($m))->unique();\nif ($types->count() > 1) {\n    throw new \\LogicException('Collection mixes model types: ' . $types->implode(', '));\n}\n// safe to dispatch\ndispatch(new ProcessCollection($collection));","typeGuard":"function containsSingleModelType(\\Illuminate\\Support\\Collection $c): bool\n{\n    return $c->map(fn ($m) => get_class($m))->unique()->count() === 1;\n}","tryCatchPattern":"try {\n    dispatch(new ProcessCollection($collection));\n} catch (\\LogicException $e) {\n    if (str_contains($e->getMessage(), 'multiple model types')) {\n        $collection->groupBy(fn ($m) => get_class($m))\n            ->each(fn ($group) => dispatch(new ProcessCollection($group)));\n    } else {\n        throw $e;\n    }\n}","preventionTips":["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."],"tags":["eloquent","collection","queue","serialization"],"backgroundTag":null,"analyzedSha":"e0f6eb3518ac29fbbca8529e97d0df7fc9f24481","analyzedAt":"2026-08-11T20:52:37.562Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}