BookStackApp/BookStack · info · ConfirmationEmailException

errors.email_already_confirmed

Error message

errors.email_already_confirmed

What it means

ConfirmationEmailException thrown by EmailConfirmationService::sendConfirmation when the given user's email_confirmed flag is already true. Sending a confirmation email to an already-confirmed account is meaningless, so the service aborts with a message and redirects to /login.

Source

Thrown at app/Access/EmailConfirmationService.php:25

use BookStack\Users\Models\User;
use Exception;

class EmailConfirmationService extends UserTokenService
{
    protected string $tokenTable = 'email_confirmations';
    protected int $expiryTime = 24;

    /**
     * Create new confirmation for a user,
     * Also removes any existing old ones.
     *
     * @throws ConfirmationEmailException
     * @throws Exception
     */
    public function sendConfirmation(User $user): void
    {
        if ($user->email_confirmed) {
            throw new ConfirmationEmailException(trans('errors.email_already_confirmed'), '/login');
        }

        $this->deleteByUser($user);
        $token = $this->createTokenForUser($user);

        $user->notify(new ConfirmEmailNotification($token));
    }

    /**
     * Check if confirmation is required in this instance.
     */
    public function confirmationRequired(): bool
    {
        return setting('registration-confirmation')
            || setting('registration-restrict');
    }
}

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. No action needed by the user — the account is already confirmed; proceed to log in
  2. If you are the admin, verify the user's email_confirmed status before resending
  3. In code, check $user->email_confirmed before calling sendConfirmation
  4. If the flag is wrongly true (user never got email), set email_confirmed back to false and resend

Example fix

// before
$service->sendConfirmation($user);
// after
if (!$user->email_confirmed) {
    $service->sendConfirmation($user);
}
Defensive patterns

Strategy: validation

Validate before calling

if ($user->email_confirmed) {
    return; // already confirmed, skip sending
}

Type guard

function needsConfirmation(\BookStack\Users\User $user): bool {
    return $user->email_confirmed === false;
}

Try / catch

try {
    $emailConfirmationService->sendConfirmation($user);
} catch (\BookStack\Access\Exceptions\ConfirmationEmailException $e) {
    // user already confirmed
}

Prevention

When it happens

Trigger: Calling sendConfirmation($user) (e.g. via the 'resend confirmation' action or admin resend) for a user whose email_confirmed column is already 1/true.

Common situations: User double-clicks the resend button or retries after the email already worked; admin manually resends for a confirmed user; user confirms in another tab then requests again; seeded/imported users already marked confirmed.

Related errors


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