Laravel Queue "has been attempted too many times or run too long" error

Janez Cergolj

Have you ever encountered the "has been attempted too many times or run too long" Laravel queue error? It's a an issue that can be frustrating to debug. Most solutions to this problem revolve around the retry_after parameter in the config/queue.php file, but there's another reason why you might be getting this error that isn't talked about much.

If you use $tries, $backoff parameter, and retryUntil() method inside the same job, you need to follow an important rule: $tries * $backoff < retryUntil time in the future.

To illustrate this, let's take a look at two examples. In the first example, the number of tries is 5, and there is a 1-second delay between each try. Assuming the time needed for job execution is negligible, the retryUntil() method is set to 10 seconds in the future, which means 5 seconds is less than 10 seconds. This setup will work without throwing an error.

<?php

class DemoJob implements ShouldQueue
{
    use Dispatchable, Queueable;

    public $tries = 5;

    public $backoff = 1;

    public function handle(): void
    {
        throw new Exception("Error");
    }

    public function retryUntil()
    {
        return now()->addSeconds(10);
    }
}

In the second example, the number of tries is 5, and there is a 5-second delay between each attempt. Again, assuming the time needed for job execution is negligible, the retryUntil() method is still set to 10 seconds in the future. However, this setup will not work and will throw the "has been attempted too many times" error. Why? Because 25 seconds is more than 10 seconds.

<?php

class DemoJob implements ShouldQueue
{
    use Dispatchable, Queueable;

    public $tries = 5;

    public $backoff = 5;

    public function handle(): void
    {
        throw new Exception("Error");
    }

    public function retryUntil()
    {
        return now()->addSeconds(10);
    }
}

To avoid this error, you can either remove either the $tries parameter or the retryUntil() method and just use one.

Remember, always follow the rule: $tries * $backoff < retryUntil time in the future.

So next time you encounter the "has been attempted too many times or run too long" error in Laravel queues, remember this rule and save yourself some time and frustration.