{"id":"5691f6a77f66f891","repo":"laravel/framework","slug":"invalid-scheduled-callback-event-must-be-a-string","errorCode":null,"errorMessage":"Invalid scheduled callback event. Must be a string or callable.","messagePattern":"Invalid scheduled callback event\\. Must be a string or callable\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Console/Scheduling/CallbackEvent.php","lineNumber":55,"sourceCode":"     *\n     * @var \\Throwable|null\n     */\n    protected $exception;\n\n    /**\n     * Create a new event instance.\n     *\n     * @param  \\Illuminate\\Console\\Scheduling\\EventMutex  $mutex\n     * @param  string|callable  $callback\n     * @param  array  $parameters\n     * @param  \\DateTimeZone|string|null  $timezone\n     *\n     * @throws \\InvalidArgumentException\n     */\n    public function __construct(EventMutex $mutex, $callback, array $parameters = [], $timezone = null)\n    {\n        if (! is_string($callback) && ! Reflector::isCallable($callback)) {\n            throw new InvalidArgumentException(\n                'Invalid scheduled callback event. Must be a string or callable.'\n            );\n        }\n\n        $this->mutex = $mutex;\n        $this->callback = $callback;\n        $this->parameters = $parameters;\n        $this->timezone = $timezone;\n    }\n\n    /**\n     * Run the callback event.\n     *\n     * @param  \\Illuminate\\Contracts\\Container\\Container  $container\n     * @return mixed\n     *\n     * @throws \\Throwable\n     */","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/laravel/framework/blob/bd6b5437e6ad87bb49f9b426724f07a9f64e9683/src/Illuminate/Console/Scheduling/CallbackEvent.php#L37-L73","documentation":"Thrown by CallbackEvent::__construct() (src/Illuminate/Console/Scheduling/CallbackEvent.php:55) when the callback is neither a string nor something Reflector::isCallable() accepts. The scheduler wraps user callbacks in CallbackEvent and refuses values it cannot later invoke via the container.","triggerScenarios":"Schedule::call($x) where $x is an array that isn't a valid callable array, an object without __invoke, a non-existent class/method string, or a plain scalar. Schedule::job() or other API misuse that ultimately constructs a CallbackEvent with an invalid callback.","commonSituations":"Passing a class-name string of a non-invokable class, passing an array ['Class', 'method'] where the method doesn't exist, or accidentally passing null/false from a bad variable.","solutions":["Pass a Closure: Schedule::call(fn () => doWork()).","Pass a callable string 'Class@method' or 'Class::method' that the container can resolve.","Pass an invokable object (instance with __invoke).","For job dispatch use Schedule::job(SomeJob::class) rather than Schedule::call(SomeJob::class) when the class isn't invokable."],"exampleFix":"// before\n$schedule->call(ReportGenerator::class)->daily();  // not invokable\n\n// after\n$schedule->call(fn () => app(ReportGenerator::class)->run())->daily();\n// or\n$schedule->job(new ReportGenerator)->daily();","handlingStrategy":"type-guard","validationCode":"use Illuminate\\Support\\Reflector;\nif (! is_string($cb) && ! Reflector::isCallable($cb)) {\n    // convert to a Closure or invokable object before Schedule::call()\n}","typeGuard":"use Illuminate\\Support\\Reflector;\nfunction isValidCallback($cb): bool\n{\n    return is_string($cb) || Reflector::isCallable($cb);\n}","tryCatchPattern":"try {\n    $schedule->call($cb)->daily();\n} catch (\\InvalidArgumentException $e) {\n    $schedule->call(fn () => null)->daily(); // safe fallback\n}","preventionTips":["Prefer Closures for Schedule::call().","For class-based callbacks use Schedule::job() or invokable classes.","Validate dynamic callback inputs before scheduling."],"tags":["scheduling","console","callable","laravel"],"analyzedSha":"bd6b5437e6ad87bb49f9b426724f07a9f64e9683","analyzedAt":"2026-08-06T00:28:32.783Z","schemaVersion":2}