BookStackApp/BookStack · error · NotifyException

errors.users_cannot_delete_only_admin

Error message

errors.users_cannot_delete_only_admin

What it means

UserRepo::ensureDeletable() throws NotifyException (a user-facing redirect-with-message exception) when an admin attempts to delete the only remaining admin account. Deleting the last admin would leave the instance with no user able to administer it, so BookStack refuses the operation and redirects the user back to the edit page with errors.users_cannot_delete_only_admin.

Source

Thrown at app/Users/UserRepo.php:253

            'sessions' => ['user_id'],
        ];

        foreach ($toNullify as $table => $columns) {
            foreach ($columns as $column) {
                DB::table($table)
                    ->where($column, '=', $user->id)
                    ->update([$column => null]);
            }
        }
    }

    /**
     * @throws NotifyException
     */
    protected function ensureDeletable(User $user): void
    {
        if ($this->isOnlyAdmin($user)) {
            throw new NotifyException(trans('errors.users_cannot_delete_only_admin'), $user->getEditUrl());
        }

        if ($user->system_name === 'public') {
            throw new NotifyException(trans('errors.users_cannot_delete_guest'), $user->getEditUrl());
        }
    }

    /**
     * Migrate ownership of items in the system from one user to another.
     */
    protected function migrateOwnership(User $fromUser, User|null $toUser): void
    {
        $newOwnerValue = $toUser ? $toUser->id : null;
        DB::table('entities')
            ->where('owned_by', '=', $fromUser->id)
            ->update(['owned_by' => $newOwnerValue]);
    }

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Promote another user to the Admin role first, then delete the original admin
  2. Instead of deleting, disable or archive the user while keeping admin coverage
  3. Transfer ownership of content and use 'manage users' to assign a new admin
  4. Catch NotifyException in custom code to render a friendly message and redirect

Example fix

// before
$this->userRepo->destroy($lastAdminUser);
// after
if (!$this->userRepo->isOnlyAdmin($lastAdminUser)) {
    $this->userRepo->destroy($lastAdminUser);
}
Defensive patterns

Strategy: validation

Validate before calling

// Check before deleting
if ($userRepo->isOnlyAdmin($user)) {
    return back()->withErrors('Cannot delete the only admin.');
}
$userRepo->destroy($user);

Type guard

function isSafeToDelete(\BookStack\Users\User $u, \BookStack\Users\UserRepo $repo): bool {
    return !$repo->isOnlyAdmin($u) && $u->system_name !== 'public';
}

Try / catch

try {
    $userRepo->destroy($user);
} catch (\BookStack\Exceptions\NotifyException $e) {
    return redirect($e->redirectUrlTo ?? url('/'))->with('error', $e->getMessage());
}

Prevention

When it happens

Trigger: Users/UserController destroy flow calling UserRepo::destroy on a user for whom isOnlyAdmin() returns true — i.e. the target user has admin role and is the sole member of that role.

Common situations: Single-admin BookStack instances where the owner tries to delete their own account via the UI or API without first promoting another user to admin.

Related errors


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/73daa8926c074e6e. Report an issue: GitHub.