{"record":{"id":"b3db3fe4e3a64c86","repo":"flarum/framework","slug":"cannot-delete-the-root-admin","errorCode":null,"errorMessage":"Cannot delete the root admin","messagePattern":"Cannot delete the root admin","errorType":"exception","errorClass":"DomainException","httpStatus":null,"severity":"error","filePath":"framework/core/src/User/User.php","lineNumber":162,"sourceCode":"     *\n     * @var callable[]\n     */\n    protected static array $passwordCheckers;\n\n    /**\n     * Difference from the current `last_seen` attribute value before `updateLastSeen()`\n     * will update the attribute on the DB. Measured in seconds.\n     */\n    private const LAST_SEEN_UPDATE_DIFF = 180;\n\n    public static function boot()\n    {\n        parent::boot();\n\n        // Don't allow the root admin to be deleted.\n        static::deleting(function (self $user) {\n            if ($user->id == 1) {\n                throw new DomainException('Cannot delete the root admin');\n            }\n\n            $avatarPath = $user->getRawOriginal('avatar_url');\n\n            if ($avatarPath) {\n                resolve(AvatarUploader::class)->deleteAllVariants($avatarPath);\n            }\n        });\n\n        static::deleted(function (self $user) {\n            $user->raise(new Deleted($user));\n\n            Notification::whereSubject($user)->delete();\n        });\n\n        static::creating(function (self $user) {\n            $user->joined_at = Carbon::now();\n","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/flarum/framework/blob/4b939f685389bfe8a380e9e28ddf305a1c66950c/framework/core/src/User/User.php#L144-L180","documentation":"The User model's boot() registers a `deleting` hook that throws a DomainException when the user being deleted has id 1, protecting the root admin account from deletion. This is a hard business rule of the forum: exactly one seeded super-admin must always exist. Any deletion attempt (Eloquent delete(), mass delete, etc.) on that row is aborted.","triggerScenarios":"Calling $user->delete() (or User::destroy(1), bulk deletes matching id 1, or cascade paths) on the user with id == 1.","commonSituations":"Seeders or cleanup scripts that purge inactive users including id 1; admin panel user deletion on the original admin; GDPR/erasure jobs that attempt to hard-delete every account.","solutions":["Skip user id 1 in deletion loops/cron jobs","Reassign or demote other admins instead of deleting the root account","If the account data must be erased, anonymise its columns rather than deleting the row","For fresh installs where id 1 is a mistake, rebuild the database so the intended admin is the seeded root"],"exampleFix":"// before\nUser::where('last_active', '<', $cutoff)->each->delete();\n// after\nUser::where('last_active', '<', $cutoff)->where('id', '!=', 1)->each->delete();","handlingStrategy":"try-catch","validationCode":"if ($user->id === 1) { /* skip deletion or anonymise instead */ }","typeGuard":null,"tryCatchPattern":"try { $user->delete(); } catch (DomainException $e) { Log::notice('Root admin deletion blocked'); continue; }","preventionTips":["Exclude id 1 in bulk-deletion queries and cleanup jobs","Provide an anonymisation path for the root account","Never rely on cascading deletes that can reach the root admin"],"tags":["eloquent","domain-rule","user-management","deletion"],"backgroundTag":"invalid-state-transition","analyzedSha":"4b939f685389bfe8a380e9e28ddf305a1c66950c","analyzedAt":"2026-09-15T18:09:20.879Z","contentChangedAt":"2026-09-15T18:09:20.879Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}