SerializedQueuedModel

Emitted when a class implementing Illuminate\Contracts\Queue\ShouldQueue holds an Eloquent model (or an Eloquent\Collection) in a property, and the class has no __serialize() or __sleep() of its own, inherited, or brought in by a trait.

One report per class, on the class declaration, naming the offending properties (the first three of them). The fix is a single use SerializesModels;, so a per-property report would be several findings for one edit.

Enabled by default and reported at error levels 1 to 4, info at looser levels. Disable it with the findSerializedQueuedModels flag (see Configuration).

Why this is a problem

SerializesModels::__serialize() replaces each model with a ModelIdentifier and re-resolves it in __unserialize(). Without the trait, the whole model goes into the queue payload:

  • the worker runs against a snapshot taken at dispatch time, not current data
  • payloads grow with the model’s attributes and every loaded relation
  • a payload written before a schema change can fail to unserialize after it

Examples

// Bad — the entire Customer, with whatever relations were loaded, is written into the payload
class SendCustomerReport implements ShouldQueue
{
    use Queueable; // Illuminate\Bus\Queueable — no SerializesModels

    public function __construct(public Customer $customer) {}
}
// Good — only a ModelIdentifier is serialized, and the worker reloads the row
class SendCustomerReport implements ShouldQueue
{
    use Queueable;
    use SerializesModels;

    public function __construct(public Customer $customer) {}
}

What is not reported

A queued class that ends up with a __serialize() or __sleep(), whether from SerializesModels (directly, through a parent, or through a trait that itself uses it), from another trait, or hand-written. That covers Illuminate\Foundation\Queue\Queueable, which make:job scaffolds since Laravel 11, and Illuminate\Notifications\Notification.

Also silent: abstract classes, static properties, and properties inherited from a parent or declared by a trait.

Known blind spots, all in the safe direction:

  • models held in a plain array, and Support\Collection of models (not a QueueableCollection, so the trait would not convert it either)
  • queued event listeners, whose own properties never enter the payload: Laravel queues a CallQueuedListener wrapper and re-resolves the listener from the container

How to fix

Add use SerializesModels; to the queued class, or replace a hand-assembled trait list with Illuminate\Foundation\Queue\Queueable.

If a property deliberately holds a detached model that must survive as-is, suppress the issue in the class docblock with @psalm-suppress SerializedQueuedModel and say why in a comment. The report is class-level, so a property-level suppression does not reach it.


This site uses Just the Docs, a documentation theme for Jekyll.