laravel/framework · error · InvalidArgumentException
Global scope must be an instance of Closure or Scope or be…
Error message
Global scope must be an instance of Closure or Scope or be a class name of a class extending Illuminate\Database\Eloquent\Scope
What it means
Thrown by Model::addGlobalScope() when the arguments do not match any accepted signature. addGlobalScope accepts: a (string identifier, Closure|Scope) pair, a lone Closure, a lone Scope instance, or a string class name of a Scope subclass. Any other combination (e.g. a string with a non-Scope implementation, a random object, or a class string that is not a Scope subclass) hits the final else and throws.
Solutions
- Make a class-based scope extend Illuminate\Database\Eloquent\Scope and implement apply($builder, $model).
- Pass a Closure as the implementation when using a string identifier: addGlobalScope('active', fn (Builder $q) => $q->where('active', true)).
- Pass a single Scope instance: addGlobalScope(new ActiveScope).
- Double-check argument order and types against the four accepted signatures.
Example fix
// before
User::addGlobalScope('active', 'where active = 1'); // string is not Closure|Scope
// after
User::addGlobalScope('active', function (Builder $query) {
$query->where('active', true);
}); Defensive patterns
Strategy: validation
Validate before calling
use Illuminate\Database\Eloquent\Scope;
use Closure;
$scope = 'active';
$impl = fn (\Illuminate\Database\Eloquent\Builder $q) => $q->where('active', true);
$ok = (is_string($scope) && ($impl instanceof Closure || $impl instanceof Scope))
|| $scope instanceof Closure
|| $scope instanceof Scope
|| (is_string($scope) && class_exists($scope) && is_subclass_of($scope, Scope::class));
if (! $ok) {
throw new \LogicException('Invalid global scope signature');
}
User::addGlobalScope($scope, $impl); Type guard
function isValidScopeSignature(mixed $scope, mixed $implementation = null): bool
{
if (is_string($scope) && ($implementation instanceof \Closure || $implementation instanceof \Illuminate\Database\Eloquent\Scope)) {
return true;
}
if ($scope instanceof \Closure || $scope instanceof \Illuminate\Database\Eloquent\Scope) {
return true;
}
return is_string($scope) && class_exists($scope) && is_subclass_of($scope, \Illuminate\Database\Eloquent\Scope::class);
} Prevention
- Class-based scopes must `extends \Illuminate\Database\Eloquent\Scope` and implement apply().
- Prefer passing a Closure for ad-hoc scopes, or a Scope instance for reusable ones.
- Match the argument order exactly to one of the four documented signatures.
When it happens
Trigger: Calling addGlobalScope('name', $notAClosureOrScope); addGlobalScope(SomeClass::class) where SomeClass does not extend Illuminate\Database\Eloquent\Scope; addGlobalScope($string, $string); or passing an instance whose class is not a Scope. The check cascade rejects all of these.
Common situations: Refactoring a scope from a Closure to a class but forgetting to make it extend Scope; passing a builder macro or query callback where a Scope is expected; passing a string identifier without a corresponding implementation; namespace mismatch on a Scope subclass.
Related errors
- Call to undefined cast
- Could not verify the hashed value's configuration.
- records were found.
- Expected class to implement guessResourceName method. Make…
- Failed to find resource class for model
AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11).
Data as JSON: /api/errors/c8ca1cff330e2c6c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Illuminate/Database/Eloquent/Concerns/HasGlobalScopes.php:75
* @param \Illuminate\Database\Eloquent\Scope|(\Closure(\Illuminate\Database\Eloquent\Builder<static>): mixed)|string $scope
* @param \Illuminate\Database\Eloquent\Scope|(\Closure(\Illuminate\Database\Eloquent\Builder<static>): mixed)|null $implementation
* @return mixed
*
* @throws \InvalidArgumentException
*/
public static function addGlobalScope($scope, $implementation = null)
{
if (is_string($scope) && ($implementation instanceof Closure || $implementation instanceof Scope)) {
return static::$globalScopes[static::class][$scope] = $implementation;
} elseif ($scope instanceof Closure) {
return static::$globalScopes[static::class][spl_object_hash($scope)] = $scope;
} elseif ($scope instanceof Scope) {
return static::$globalScopes[static::class][get_class($scope)] = $scope;
} elseif (is_string($scope) && class_exists($scope) && is_subclass_of($scope, Scope::class)) {
return static::$globalScopes[static::class][$scope] = new $scope;
}
throw new InvalidArgumentException('Global scope must be an instance of Closure or Scope or be a class name of a class extending '.Scope::class);
}
/**
* Register multiple global scopes on the model.
*
* @param array $scopes
* @return void
*/
public static function addGlobalScopes(array $scopes)
{
foreach ($scopes as $key => $scope) {
if (is_string($key)) {
static::addGlobalScope($key, $scope);
} else {
static::addGlobalScope($scope);
}
}
}View on GitHub (pinned to e0f6eb3518)