laravel/framework · error · RuntimeException
Unable to bind custom driver callback
Error message
Unable to bind custom driver callback
What it means
Thrown by FilesystemManager::extend() when bindCallbackToSelf() returns null, indicating the supplied Closure could not be re-bound to the manager instance. extend() needs the closure bound so that custom driver creators receive $this context; a null result is treated as a hard failure to register the driver.
Source
Thrown at src/Illuminate/Filesystem/FilesystemManager.php:448
$name ??= $this->getDefaultDriver();
unset($this->disks[$name]);
}
/**
* Register a custom driver creator Closure.
*
* @param string $driver
* @param \Closure $callback
*
* @param-closure-this $this $callback
*
* @return $this
*/
public function extend($driver, Closure $callback)
{
try {
$callback = $this->bindCallbackToSelf($callback) ?? throw new RuntimeException('Unable to bind custom driver callback');
} catch (ReflectionException $e) {
throw new RuntimeException('Unable to bind custom driver callback', previous: $e);
}
$this->customCreators[$driver] = $callback;
return $this;
}
/**
* Set the application instance used by the manager.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return $this
*/
public function setApplication($app)
{
$this->app = $app;View on GitHub (pinned to bd6b5437e6)
Solutions
- Pass a non-static Closure that does not rely on $this if you don't need it, or accept the manager as the first argument ($app, $config) instead.
- Avoid static closures when registering via extend().
- If you need $this, register the closure as a normal method or use a class with __invoke.
Example fix
// before - static closure cannot be bound, extend() returns null
Storage::extend('gcs', static fn ($app, $config) => makeGcs($config));
// after - regular closure
Storage::extend('gcs', function ($app, $config) {
return makeGcs($config);
}); Defensive patterns
Strategy: validation
Validate before calling
// Reject static closures before registering
$ref = new \ReflectionFunction($callback);
if ($ref->isStatic()) {
throw new \InvalidArgumentException('Cannot bind a static closure via extend()');
}
Storage::extend($driver, $callback); Type guard
function isBindableClosure(Closure $c): bool
{
return ! (new \ReflectionFunction($c))->isStatic();
} Try / catch
try {
Storage::extend($driver, $callback);
} catch (\RuntimeException $e) {
if (str_contains($e->getMessage(), 'Unable to bind custom driver callback')) {
// fall back to invokable class
Storage::extend($driver, $invokableClassInstance);
} else {
throw $e;
}
} Prevention
- Avoid static closures when calling extend().
- Use a regular closure or an invokable class instead.
- Let the closure accept ($app, $config) rather than relying on $this.
When it happens
Trigger: Calling Storage::extend($driver, $callback) with a closure that uses $this but cannot be reflected/rebound - e.g. a Closure from an internal source, a static closure, or a closure whose reflection is blocked.
Common situations: Passing a static closure (static fn) that can't be bound; wrapping a closure in a way that loses its binding; PHP version-specific reflection quirks on certain Closure types.
Related errors
- Unable to bind custom driver callback
- Unable to bind custom driver callback
- The environment property must be set and cannot be empty.
- {self::class}::bind(): Argument #2 ($concrete) must be of ty
- Target [$concrete] is not instantiable while building [$prev
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/5510e3c541779e16.json.
Report an issue: GitHub.