#MaxAttemptsExceededException error after 3 minutes of job execution

3 messages · Page 1 of 1 (latest)

limpid junco
#

Description

I'm facing an issue in production: the SyncBudgetForOrganisationJob fails with MaxAttemptsExceededException after running for only 3 minutes.

Weird things:

  • Works fine on localhost.
  • Job timeout is set to 600 (10 minutes).
  • PHP max_execution_time = 300 (5 minutes).
  • Queue scheduler has retry_after = 660 seconds.
  • In horizon.php, supervisor-4 timeout is set to 10 minutes (timeout => 60 * 10).
  • tries = 1, but the payload shows attempts = 2.

Relevant code

Queue config (queue.php)

'scheduler' => [
    'driver'       => 'redis',
    'connection'   => 'default',
    'queue'        => 'scheduler',
    'retry_after'  => 660,
    'block_for'    => null,
    'after_commit' => false,
],

Horizon config (horizon.php)

'supervisor-4' => [
    'connection'      => 'redis',
    'queue'           => ['scheduler'],
    'maxProcesses'    => env('HORIZON_MAX_PROCESSES_SCHEDULER', 5),
    'tries'           => 1,
    'balanceMaxShift' => 1,
    'balanceCooldown' => 3,
    'timeout'         => 60 * 10,
],
#

Job class

class SyncBudgetForOrganisationJob implements ShouldQueue, ShouldBeUnique
{
    use Queueable, SerializesModels;

    public $tries = 1;
    public $timeout = 60*10;

    public bool $failOnTimeout = true;

    public function __construct(public Organisation $organisation)
    {

    }
    public function handle(ScheduleBudgetService $service): void
    {
        try {
            $service->syncCampaigns($this->organisation);
        } catch (\Throwable $e) {
            \Log::error('SyncBudgetForOrganisationJob failed', [
                'organisation_id' => $this->organisation->id,
                'error'           => $e->getMessage(),
                $e,
            ]);
            $this->fail($e);
        }
    }
    public function uniqueId()
    {
        return 'u_SyncBudgetForOrganisationJob_' . $this->organisation->id;
    }
   
}

Job payload (why 2 attempts?)

{
  "backoff": null,
  "timeout": 600,
  "id": "273fad6a-c7f9-46fa-a036-bfe86bb3ba9b",
  "pushedAt": "1739544960.9021",
  "maxExceptions": null,
  "maxTries": 1,
  "failOnTimeout": true,
  "silenced": false,
  "retryUntil": null,
  "type": "job",
  "displayName": "App\\Jobs\\SyncBudgetForOrganisationJob",
  "attempts": 2
}

What I've tried

✅ Cleared cache: php artisan cache:clear && php artisan config:clear
✅ Flushed Redis
✅ Restarted supervisor
✅ Removed withoutOverlapping
✅ Tried adjusting timeout settings

Everything works fine in dev, but in production, the job gets killed after 3 minutes.
Why is Laravel retrying the job (attempts = 2) when tries = 1?
Why does it time out after 3 minutes when timeout = 10 minutes?

Any ideas? Thanks in advance! 🙌

#

I publish a question for the first time, issued and provided all the necessary information and also read the rules of publication, I will be glad if you help, thanks