If you use queues in Laravel, you most likely encountered the Job has timed out error when processing jobs in a queue. In older versions of Laravel you can see this error message directly in the terminal or the failed_jobs database table after the job has failed when job is running longer than 60 seconds.
By default, queued jobs in Laravel queues can run up to 60 seconds. When this time expires, the queue worker kills the job. But very often, it is needed to keep job running much longer. In this article, I will show how to fix this issue differently.
Table of Contents
Why the Error Occurs?
This error is caused by Laravel but not the PHP engine. PHP has its maximum execution time limit for scripts, but this limit does not affect command line scripts even if you change its value in php.ini. You can ensure that the value of the max_execution_time parameter is not applied using the following command:
php -i | grep "max_execution_time"
In any case, 0 will be displayed. Now let’s have a look at how it is implemented in Laravel. The framework has the Illuminate/Queue/WorkerOptions class, which contains default options for queue workers. You can see the default maximum number of seconds in $timeout argument in its constructor. In the Laravel 10, it is 60:
Let’s make an example Job class that needs more than 60 seconds to be handled and push it into the queue, to check how Laravel handles long-running tasks. I will create a new job with following code that will wait for 70 seconds and exit:
app/Jobs/SomeJob.php<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SomeJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public function __construct()
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
$i = 0;
$secondsToWait = 70;
$start = hrtime()[0];
while (hrtime()[0] - $start < $secondsToWait) {
$i++;
}
}
}
Then, push the new job into a queue. I have created a simple command app:push-some-job-to-queue that helps with it and uses default queue and default job timeout.
php artisan app:push-some-job-to-queue
php artisan queue:work
As expected, after 60 seconds of processing, the job will be marked as failed, and a record with the reason will appear in the failed_jobs table:
You can increase the timeout in two different ways. The first way is to override the default timeout in the Job class. The second and most useful – add the –timeout option for the queue:work command.
Fixing The Job Timed Out Error in Laravel
1. Modify a Job Class
You can add the $timeout property into the job class with the desired timeout in seconds or just zero to disable the limit. Just add the following code before a class constructor:
app/Jobs/SomeJob.phppublic $timeout = 0;
After this, you can re-push failed job to the queue and ensure that everything works fine:
2. Add Option to the Worker
If you don’t want to modify the application code or have too many Job classes, you can configure the timeout once for Laravel queue worker in your process manager. For example, to disable the time limit, add the –timeout 0 option to the queue:work artisan command:
php artisan queue:work --timeout 0
This worker will handle the new queued job without any time limit:
Wrapping Up
In this article, I have explained how to fix the job timed-out error in Laravel. It is pretty easy, and usually, you can configure the queue worker properly and forget about this issue.