{"id":"7dfb8084281a172f","repo":"laravel/framework","slug":"global-scope-must-be-an-instance-of-closure-or-sco","errorCode":null,"errorMessage":"Global scope must be an instance of Closure or Scope or be a class name of a class extending {Scope::class}","messagePattern":"Global scope must be an instance of Closure or Scope or be a class name of a class extending (.+?)","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Database/Eloquent/Concerns/HasGlobalScopes.php","lineNumber":75,"sourceCode":"     * @param  \\Illuminate\\Database\\Eloquent\\Scope|(\\Closure(\\Illuminate\\Database\\Eloquent\\Builder<static>): mixed)|string  $scope\n     * @param  \\Illuminate\\Database\\Eloquent\\Scope|(\\Closure(\\Illuminate\\Database\\Eloquent\\Builder<static>): mixed)|null  $implementation\n     * @return mixed\n     *\n     * @throws \\InvalidArgumentException\n     */\n    public static function addGlobalScope($scope, $implementation = null)\n    {\n        if (is_string($scope) && ($implementation instanceof Closure || $implementation instanceof Scope)) {\n            return static::$globalScopes[static::class][$scope] = $implementation;\n        } elseif ($scope instanceof Closure) {\n            return static::$globalScopes[static::class][spl_object_hash($scope)] = $scope;\n        } elseif ($scope instanceof Scope) {\n            return static::$globalScopes[static::class][get_class($scope)] = $scope;\n        } elseif (is_string($scope) && class_exists($scope) && is_subclass_of($scope, Scope::class)) {\n            return static::$globalScopes[static::class][$scope] = new $scope;\n        }\n\n        throw new InvalidArgumentException('Global scope must be an instance of Closure or Scope or be a class name of a class extending '.Scope::class);\n    }\n\n    /**\n     * Register multiple global scopes on the model.\n     *\n     * @param  array  $scopes\n     * @return void\n     */\n    public static function addGlobalScopes(array $scopes)\n    {\n        foreach ($scopes as $key => $scope) {\n            if (is_string($key)) {\n                static::addGlobalScope($key, $scope);\n            } else {\n                static::addGlobalScope($scope);\n            }\n        }\n    }","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/laravel/framework/blob/bd6b5437e6ad87bb49f9b426724f07a9f64e9683/src/Illuminate/Database/Eloquent/Concerns/HasGlobalScopes.php#L57-L93","documentation":"addGlobalScope() accepts exactly four shapes: a Closure, a Scope instance, a Scope subclass name string, or a name string paired with a Closure/Scope implementation. Anything else (random string, non-Scope object, scalar) is rejected with InvalidArgumentException because the scope cannot be applied.","triggerScenarios":"Calling Model::addGlobalScope('active', 'App\\Scopes\\MissingScope') where the class does not extend Scope or does not exist; passing an object that is not a Scope; passing a string that is not a class with no implementation argument.","commonSituations":"Custom scope class forgetting to implement Illuminate\\Database\\Eloquent\\Scope; passing a query-builder macro or a callable array (['Obj','method']) which is not a Closure; refactoring that dropped the Scope interface.","solutions":["Make the scope class implement Illuminate\\Database\\Eloquent\\Scope (with apply(Builder,Model)).","Pass a Closure: Model::addGlobalScope(fn (Builder $b) => $b->where('active', 1)).","If using a string class, ensure it extends/implements Scope and the class is autoloadable."],"exampleFix":"// before\nModel::addGlobalScope('active', \\App\\Scopes\\ActiveScope::class);\n// ActiveScope does not implement Scope\n\n// after\nclass ActiveScope implements \\Illuminate\\Database\\Eloquent\\Scope\n{\n    public function apply(Builder $builder, Model $model): void\n    {\n        $builder->where('active', true);\n    }\n}","handlingStrategy":"type-guard","validationCode":"use Illuminate\\Database\\Eloquent\\Scope;\nif ($scope instanceof \\Closure || $scope instanceof Scope) {\n    Model::addGlobalScope($name, $scope);\n} elseif (is_string($scope) && is_subclass_of($scope, Scope::class)) {\n    Model::addGlobalScope($scope);\n} else {\n    throw new \\InvalidArgumentException('Invalid global scope: ' . get_debug_type($scope));\n}","typeGuard":"function isValidScope(mixed $scope): bool\n{\n    return $scope instanceof \\Closure\n        || $scope instanceof \\Illuminate\\Database\\Eloquent\\Scope\n        || (is_string($scope) && is_subclass_of($scope, \\Illuminate\\Database\\Eloquent\\Scope::class));\n}","tryCatchPattern":"try {\n    Model::addGlobalScope($name, $impl);\n} catch (\\InvalidArgumentException $e) {\n    if (str_contains($e->getMessage(), 'Global scope must be')) {\n        report('Invalid scope registration: ' . get_debug_type($impl));\n    }\n    throw $e;\n}","preventionTips":["Implement Scope (with apply()) on scope classes; do not just name them 'scope'.","Prefer Closures for one-off scopes and Scope instances for reusable ones.","Add a unit test asserting each global scope class implements Scope."],"tags":["eloquent","global-scope","query","config","type-error"],"analyzedSha":"bd6b5437e6ad87bb49f9b426724f07a9f64e9683","analyzedAt":"2026-08-06T00:28:32.783Z","schemaVersion":2}