laravel/framework · error · LogicException

Queueing collections with multiple model types is not suppor

Error message

Queueing collections with multiple model types is not supported.

What it means

Eloquent's Collection::getQueueableClass() iterates every model when serializing a collection for the queue and requires them all to share the same class. If any model differs from the first, a LogicException is raised because PHP's queue payload can only describe one type per collection.

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 bd6b5437e6)

Solutions

  1. Split the collection by class and dispatch one job per type.
  2. Eager-load relations so each queued collection contains only one concrete type.
  3. Pass only model keys (->modelKeys()) into the job and re-fetch inside the handler instead of serializing the collection.

Example fix

// before
ProcessMedia::dispatch($post->media); // mixes Photo + Video -> throws

// after
$post->media->groupBy(fn ($m) => get_class($m))
    ->each(fn ($group) => ProcessMedia::dispatch($group));
Defensive patterns

Strategy: validation

Validate before calling

$classes = $collection->map(fn ($m) => get_class($m))->unique();
if ($classes->count() > 1) {
    throw new \LogicException('Refusing to queue mixed-type collection: ' . $classes->implode(','));
}
// safe to dispatch

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: Dispatching a queued job that receives an Eloquent Collection containing more than one model class, e.g. collect([new Post, new Comment])->... dispatched to a job, or passing $post->media (mixing Photo and Video models without a shared base morph class) to a Bus::dispatchToQueue job.

Common situations: Polymorphic collections built from union of multiple query results; merging related models of different types into one collection before queueing; using a base class that getQueueableClassName() does not collapse to a single class.

Related errors


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