stepId); // Stale/duplicate dispatch — the step moved on (or was retried and // re-dispatched) before this run got picked up. if (! $step || $step->status !== 'in_progress') { return; } $handler = $handlers->resolve($step->type); if (! $handler) { $engine->failStep($step, "No handler registered for step type '{$step->type}'."); return; } try { $handler->handle($step, $engine); } catch (Throwable $e) { Log::error('workflow step handler threw', ['step_id' => $step->id, 'error' => $e->getMessage()]); $fresh = $step->fresh(); if ($fresh && $fresh->status === 'in_progress') { $engine->failStep($fresh, $e->getMessage()); } } } }