laravel/framework · warning · Exception

Scheduled command [{$event->command}] failed with exit code

Error message

Scheduled command [{$event->command}] failed with exit code [{$event->exitCode}].

What it means

Thrown by ScheduleRunCommand::runEvent() (src/Illuminate/Console/Scheduling/ScheduleRunCommand.php:215) when a foreground scheduled command exits with a non-zero code. It is caught internally, reported via the exception handler, and surfaces as a failed task line in the schedule:run output; background events do not raise it.

Source

Thrown at src/Illuminate/Console/Scheduling/ScheduleRunCommand.php:215

        );

        $this->components->task($description, function () use ($event) {
            $this->dispatcher->dispatch(new ScheduledTaskStarting($event));

            $start = microtime(true);

            try {
                $event->run($this->laravel);

                $this->dispatcher->dispatch(new ScheduledTaskFinished(
                    $event,
                    round(microtime(true) - $start, 2)
                ));

                $this->eventsRan = true;

                if ($event->exitCode != 0 && ! $event->runInBackground) {
                    throw new Exception("Scheduled command [{$event->command}] failed with exit code [{$event->exitCode}].");
                }
            } catch (Throwable $e) {
                $this->dispatcher->dispatch(new ScheduledTaskFailed($event, $e));

                $this->handler->report($e);
            }

            return $event->exitCode == 0;
        });

        if (! $event instanceof CallbackEvent) {
            $this->components->bulletList([
                $event->getSummaryForDisplay(),
            ]);
        }
    }

    /**

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Run the command manually with php artisan <name> to reproduce and read the actual exception.
  2. Make the command robust: catch expected exceptions and return SUCCESS or a controlled FAILURE.
  3. Add monitoring/logging inside the command; check storage/logs and the failed_jobs table.
  4. If the failure is acceptable, run the event in the background to suppress this throw, or wrap with ->onFailure(...)/->emailOutputOnFailure(...).

Example fix

// before
// command body throws -> exit code 1
$schedule->command('reports:send')->daily();

// after
// in the command handle():
try { $this->send(); return self::SUCCESS; }
catch (\Throwable $e) { $this->error($e->getMessage()); return self::FAILURE; }
// and/or
$schedule->command('reports:send')->daily()->onFailure(fn () => logger('reports failed'));
Defensive patterns

Strategy: try-catch

Validate before calling

$exit = \Illuminate\Support\Facades\Artisan::call('reports:send');
if ($exit !== 0) {
    // don't schedule a known-failing command; fix it first
}

Type guard

function commandSucceeds(string $name): bool
{
    return \Illuminate\Support\Facades\Artisan::call($name) === 0;
}

Try / catch

// handled inside ScheduleRunCommand; in your command handle():
try {
    $this->send();
    return self::SUCCESS;
} catch (\Throwable $e) {
    $this->error($e->getMessage());
    return self::FAILURE;
}

Prevention

When it happens

Trigger: A scheduled Artisan command (Event, not CallbackEvent) returns non-zero exitCode (e.g. command throws, fails an assertion, or returns self::FAILURE). Triggered when schedule:run / schedule:work executes the due event.

Common situations: Scheduled maintenance/cleanup commands that error on bad input, missing dependencies, expired credentials, or DB connectivity. Often intermittent (network/API flakiness).

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/53a63fcf167f40da.json. Report an issue: GitHub.