Updated June 2026. Tested on Laravel 13 and PHP 8.4. Part of the Techalyst queue series.
You spot this in your logs and it looks alarming.
SQLSTATE[23000]: Integrity constraint violation: 1062
Duplicate entry '3e2e41b5-2b0c-...' for key 'failed_jobs_uuid_unique'
(SQL: insert into failed_jobs (uuid, connection, queue, payload, exception, failed_at) ...)
It reads like a database problem, but it is really a symptom of a queue misconfiguration. Once you know what it is telling you, the fix is a single setting.
What the error actually means
When a job fails, Laravel records it in the failed_jobs table, keyed by the job's UUID, and that UUID column is unique. This error means Laravel tried to log the same failed job, with the same UUID, twice.
That only happens if two different workers ran the same job and both runs failed. The first worker logs the failure fine. The second worker tries to log the identical UUID and the database rejects it as a duplicate. So the real question is not "why the duplicate row", it is "why did two workers run the same job at all".
Why two workers ran the same job
A worker reserves a job for a window defined by the connection's retry_after. If the job is still running when that window passes, the queue assumes the worker died and hands the same job to a second worker. Now both are running it, and if it fails, both try to log the failure, producing the duplicate UUID error.
In other words, this error is a downstream sign of the classic duplication bug: retry_after is set shorter than how long the job actually runs.
The fix
Make sure the connection's retry_after is comfortably larger than your longest running job's timeout. With retry_after always greater than timeout, a slow job is killed by its timeout long before the queue would ever reclaim it, so a job is never run by two workers, and the duplicate UUID can never occur.
// config/queue.php
'redis' => [
'driver' => 'redis',
'retry_after' => 120, // longer than any job's timeout
],
php artisan queue:work --timeout=90 # under retry_after
On SQS the equivalent setting is the queue's Visibility Timeout, which must likewise exceed your job timeout. The full reasoning lives in why your job ran twice.
Wrapping up
The failed_jobs_uuid_unique duplicate entry error is not a database bug, it is two workers logging the same failed job because both ran it. The cause is always the same: retry_after shorter than your job timeout. Set retry_after (or the SQS visibility timeout) safely above your longest job's timeout and the duplicate disappears along with the double execution behind it.
More in the series: why your job ran twice and the queue configuration keys explained. Questions welcome below.
All comments ()
No comments yet
Be the first to leave a comment on this post.