{"id":"0f71752168031b62","repo":"laravel/framework","slug":"a-scheduled-event-name-is-required-to-prevent-over","errorCode":null,"errorMessage":"A scheduled event name is required to prevent overlapping. Use the 'name' method before 'withoutOverlapping'.","messagePattern":"A scheduled event name is required to prevent overlapping\\. Use the 'name' method before 'withoutOverlapping'\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Console/Scheduling/CallbackEvent.php","lineNumber":141,"sourceCode":"\n            return 1;\n        }\n    }\n\n    /**\n     * Do not allow the event to overlap each other.\n     *\n     * The expiration time of the underlying cache lock may be specified in minutes.\n     *\n     * @param  int  $expiresAt\n     * @return $this\n     *\n     * @throws \\LogicException\n     */\n    public function withoutOverlapping($expiresAt = 1440, $releaseOnTerminationSignals = true)\n    {\n        if (! isset($this->description)) {\n            throw new LogicException(\n                \"A scheduled event name is required to prevent overlapping. Use the 'name' method before 'withoutOverlapping'.\"\n            );\n        }\n\n        return parent::withoutOverlapping($expiresAt, $releaseOnTerminationSignals);\n    }\n\n    /**\n     * Allow the event to only run on one server for each cron expression.\n     *\n     * @return $this\n     *\n     * @throws \\LogicException\n     */\n    public function onOneServer()\n    {\n        if (! isset($this->description)) {\n            throw new LogicException(","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/laravel/framework/blob/bd6b5437e6ad87bb49f9b426724f07a9f64e9683/src/Illuminate/Console/Scheduling/CallbackEvent.php#L123-L159","documentation":"Thrown by CallbackEvent::withoutOverlapping() (src/Illuminate/Console/Scheduling/CallbackEvent.php:141) when $this->description is unset. Overlap prevention needs a stable mutex name; CallbackEvent derives it from the description (set via name()), so a nameless closure cannot be uniquely locked.","triggerScenarios":"Calling $schedule->call(fn ())->hourly()->withoutOverlapping() without first calling ->name('...'). Same for Schedule::job()/call() events that lack a name.","commonSituations":"Developers add withoutOverlapping() to a closure-based task assuming Laravel auto-names it; scheduling regression tests where name() was removed.","solutions":["Call ->name('unique-label') before ->withoutOverlapping().","Use a descriptive stable name so the mutex doesn't collide across deploys.","For jobs scheduled via Schedule::job(), a name is auto-set; ensure it isn't being reset.","Prefer scheduling a named command/job if you don't want to manage names manually."],"exampleFix":"// before\n$schedule->call(fn () => syncStock())\n    ->everyFiveMinutes()\n    ->withoutOverlapping();\n\n// after\n$schedule->call(fn () => syncStock())\n    ->name('stock-sync')\n    ->everyFiveMinutes()\n    ->withoutOverlapping();","handlingStrategy":"validation","validationCode":"if ($event instanceof \\Illuminate\\Console\\Scheduling\\CallbackEvent && ! isset($event->description)) {\n    // call name('...') before withoutOverlapping()\n}","typeGuard":"// pragmatic guard: ensure a name is set before overlap locking\nif (! $event->getSummaryForDisplay() || $event->getSummaryForDisplay() === 'Callback') {\n    $event->name('fallback-name');\n}","tryCatchPattern":"try {\n    $event->withoutOverlapping();\n} catch (\\LogicException $e) {\n    $event->name('auto-' . uniqid())->withoutOverlapping();\n}","preventionTips":["Always chain ->name('stable-id') on closure-based scheduled tasks.","Use a constant, deployment-stable name to avoid mutex churn.","Prefer scheduling real commands/jobs where naming is automatic."],"tags":["scheduling","console","mutex","laravel"],"analyzedSha":"bd6b5437e6ad87bb49f9b426724f07a9f64e9683","analyzedAt":"2026-08-06T00:28:32.783Z","schemaVersion":2}