{"record":{"id":"a41085bfe95a69e8","repo":"laravel/framework","slug":"unable-to-bind-custom-driver-callback-a41085","errorCode":null,"errorMessage":"Unable to bind custom driver callback","messagePattern":"Unable to bind custom driver callback","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Broadcasting/BroadcastManager.php","lineNumber":512,"sourceCode":"        $name = enum_value($name) ?? $this->getDefaultDriver();\n\n        unset($this->drivers[$name]);\n    }\n\n    /**\n     * Register a custom driver creator Closure.\n     *\n     * @param  string  $driver\n     * @param  \\Closure  $callback\n     *\n     * @param-closure-this  $this  $callback\n     *\n     * @return $this\n     */\n    public function extend($driver, Closure $callback)\n    {\n        try {\n            $callback = $this->bindCallbackToSelf($callback) ?? throw new RuntimeException('Unable to bind custom driver callback');\n        } catch (ReflectionException $e) {\n            throw new RuntimeException('Unable to bind custom driver callback', previous: $e);\n        }\n\n        $this->customCreators[$driver] = $callback;\n\n        return $this;\n    }\n\n    /**\n     * Execute the given callback using \"rescue\" if possible.\n     *\n     * @param  \\Closure  $callback\n     * @return mixed\n     */\n    protected function rescue(Closure $callback)\n    {\n        if (function_exists('rescue')) {","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/laravel/framework/blob/e0f6eb3518ac29fbbca8529e97d0df7fc9f24481/src/Illuminate/Broadcasting/BroadcastManager.php#L494-L530","documentation":"Thrown by BroadcastManager::extend() on the null-coalesce-throw line when bindCallbackToSelf($callback) returns null. extend() rebinds the supplied Closure so $this inside it refers to the BroadcastManager; if the rebinder cannot produce a bound closure it throws this RuntimeException. This is the null-return branch, distinct from the ReflectionException branch on the next line.","triggerScenarios":"Calling Broadcast::extend($driver, $callback) with a closure that bindCallbackToSelf cannot rebind (returns null) — most commonly a static closure, since Closure::bind returns null when binding a static closure to an instance scope.","commonSituations":"Registering a custom broadcaster with static fn (...); first-class callable syntax producing a closure whose scope cannot be rebound; PHP version differences affecting Closure::bind for static closures.","solutions":["Pass a non-static closure so it can be rebound to the BroadcastManager instance.","If the logic must not capture $this, restructure into an invokable class instantiated explicitly.","Ensure the closure is a genuine Closure object, not a stripped scope.","Verify PHP version compatibility for Closure::bind behavior."],"exampleFix":"// before — static closure cannot be rebound\nBroadcast::extend('websocket', static function ($app, array $config) {\n    return new WebsocketBroadcaster($config);\n});\n\n// after — non-static closure\nBroadcast::extend('websocket', function ($app, array $config) {\n    return new WebsocketBroadcaster($config);\n});","handlingStrategy":"validation","validationCode":"// PHP — ensure the closure is non-static before extend()\n$ref = new \\ReflectionFunction($callback);\nif ($ref->isStatic()) {\n    throw new \\RuntimeException('Cannot Broadcast::extend() with a static closure; use a non-static closure.');\n}\nBroadcast::extend($driver, $callback);","typeGuard":"function isRebindableClosure(\\Closure $c): bool {\n    return ! (new \\ReflectionFunction($c))->isStatic();\n}","tryCatchPattern":"try {\n    Broadcast::extend($driver, $callback);\n} catch (\\RuntimeException $e) {\n    Log::error('Broadcast::extend failed to bind', ['driver' => $driver, 'err' => $e->getMessage()]);\n    throw $e;\n}","preventionTips":["Avoid static closures when calling Broadcast::extend().","Use invokable classes for complex custom broadcasters.","Register extend() in a service provider's boot() method."],"tags":["broadcasting","extend","closure-binding","laravel","php"],"backgroundTag":null,"analyzedSha":"e0f6eb3518ac29fbbca8529e97d0df7fc9f24481","analyzedAt":"2026-08-11T20:52:37.562Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}