{"record":{"id":"16a2a9d2c2d32a4e","repo":"BookStackApp/BookStack","slug":"errors-email-already-confirmed","errorCode":null,"errorMessage":"errors.email_already_confirmed","messagePattern":"errors\\.email_already_confirmed","errorType":"exception","errorClass":"ConfirmationEmailException","httpStatus":null,"severity":"info","filePath":"app/Access/EmailConfirmationService.php","lineNumber":25,"sourceCode":"use BookStack\\Users\\Models\\User;\nuse Exception;\n\nclass EmailConfirmationService extends UserTokenService\n{\n    protected string $tokenTable = 'email_confirmations';\n    protected int $expiryTime = 24;\n\n    /**\n     * Create new confirmation for a user,\n     * Also removes any existing old ones.\n     *\n     * @throws ConfirmationEmailException\n     * @throws Exception\n     */\n    public function sendConfirmation(User $user): void\n    {\n        if ($user->email_confirmed) {\n            throw new ConfirmationEmailException(trans('errors.email_already_confirmed'), '/login');\n        }\n\n        $this->deleteByUser($user);\n        $token = $this->createTokenForUser($user);\n\n        $user->notify(new ConfirmEmailNotification($token));\n    }\n\n    /**\n     * Check if confirmation is required in this instance.\n     */\n    public function confirmationRequired(): bool\n    {\n        return setting('registration-confirmation')\n            || setting('registration-restrict');\n    }\n}\n","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Access/EmailConfirmationService.php#L7-L43","documentation":"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.","triggerScenarios":"Calling sendConfirmation($user) (e.g. via the 'resend confirmation' action or admin resend) for a user whose email_confirmed column is already 1/true.","commonSituations":"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.","solutions":["No action needed by the user — the account is already confirmed; proceed to log in","If you are the admin, verify the user's email_confirmed status before resending","In code, check $user->email_confirmed before calling sendConfirmation","If the flag is wrongly true (user never got email), set email_confirmed back to false and resend"],"exampleFix":"// before\n$service->sendConfirmation($user);\n// after\nif (!$user->email_confirmed) {\n    $service->sendConfirmation($user);\n}","handlingStrategy":"validation","validationCode":"if ($user->email_confirmed) {\n    return; // already confirmed, skip sending\n}","typeGuard":"function needsConfirmation(\\BookStack\\Users\\User $user): bool {\n    return $user->email_confirmed === false;\n}","tryCatchPattern":"try {\n    $emailConfirmationService->sendConfirmation($user);\n} catch (\\BookStack\\Access\\Exceptions\\ConfirmationEmailException $e) {\n    // user already confirmed\n}","preventionTips":["Check email_confirmed before any resend action in custom code","Debounce resend buttons in the UI","Sync email_confirmed state when importing users"],"tags":["email","registration","duplicate-action"],"backgroundTag":"email-already-confirmed","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}