Skip to content

Commit b6cf89d

Browse files
authored
fix: avoid duplicate ModelNotFoundException logs on orphaned queued jobs (#4634)
When a queued job's serialized model is deleted between dispatch and worker pickup, Laravel's CallQueuedHandler catches the unserialize ModelNotFoundException via handleModelNotFound. Without deleteWhenMissingModels, it then routes the job to fail(), which re-deserializes the payload and throws ModelNotFoundException a second time — this one is not caught and gets logged. Set deleteWhenMissingModels = true on AbstractJob so the handler delete()s the job (already off the queue, lock already released) instead of going through the noisy fail() path. All current AbstractJob subclasses (notification fan-out, mail sends, search index, package manager, gdpr export, etc.) are no-ops when their subject model is missing — there's no useful retry path. Subclasses that genuinely want to be retried/failed on missing models can override with `public bool $deleteWhenMissingModels = false;`. Fixes #4615
1 parent d6dc7c4 commit b6cf89d

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

framework/core/src/Queue/AbstractJob.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,16 @@ class AbstractJob implements ShouldQueue
1919
use InteractsWithQueue;
2020
use Queueable;
2121
use SerializesModels;
22+
23+
/**
24+
* If a serialized model on this job has been deleted between dispatch and
25+
* worker pickup, treat the job as a no-op and remove it from the queue
26+
* rather than calling failed(), which re-deserializes the payload and
27+
* throws ModelNotFoundException a second time — producing duplicate error
28+
* log entries for what is in fact a handled-correctly race.
29+
*
30+
* Subclasses that should be retried or marked failed in this scenario can
31+
* override with `public bool $deleteWhenMissingModels = false;`.
32+
*/
33+
public bool $deleteWhenMissingModels = true;
2234
}

0 commit comments

Comments
 (0)