{"record":{"id":"02daeb7e0f45be52","repo":"passbolt/passbolt_api","slug":"the-email-is-already-registered","errorCode":null,"errorMessage":"The email is already registered.","messagePattern":"The email is already registered\\.","errorType":"http","errorClass":"ForbiddenException","httpStatus":403,"severity":"error","filePath":"plugins/PassboltCe/SelfRegistration/src/Service/DryRun/SelfRegistrationAbstractDryRunService.php","lineNumber":61,"sourceCode":"        return $this->settings;\n    }\n\n    /**\n     * Check that the email is not assigned to a registered user.\n     *\n     * @param string $username Value to check\n     * @return void\n     * @throws \\Cake\\Http\\Exception\\ForbiddenException if the user is already registered\n     */\n    protected function checkEmailNotPreviouslyRegistered(string $username): void\n    {\n        /** @var \\App\\Model\\Table\\UsersTable $UsersTable */\n        $UsersTable = TableRegistry::getTableLocator()->get('Users');\n        $user = $UsersTable->buildEntity(compact('username'));\n        $isUnique = $UsersTable->isUniqueUsername($user);\n\n        if (!$isUnique) {\n            throw new ForbiddenException(__('The email is already registered.'));\n        }\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public function isSelfRegistrationOpen(): bool\n    {\n        $settings = $this->getSelfRegistrationSettingsInDB();\n\n        return isset($settings['provider']);\n    }\n}\n","sourceCodeStart":43,"sourceCodeEnd":75,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/SelfRegistration/src/Service/DryRun/SelfRegistrationAbstractDryRunService.php#L43-L75","documentation":"Thrown by SelfRegistrationAbstractDryRunService::checkEmailNotPreviouslyRegistered when the email supplied in the dry-run is already taken. It builds a user entity and runs UsersTable::isUniqueUsername to mirror registration-time uniqueness checks. Raised as ForbiddenException since self-registering with an existing email is disallowed.","triggerScenarios":"POST /self-registration/dry-run (or the equivalent registration flow) with a username/email that already exists in the users table.","commonSituations":"Users forgetting they already have an account; email case variants that normalize to an existing user; testing with a personal email already used; deleted-but-active usernames.","solutions":["Sign in with the existing account instead of registering again","Use the account recovery / forgot password flow for the registered email","Test the dry-run with a brand-new email address","Check active users in the admin workspace to confirm which email is taken"],"exampleFix":"// before\nawait dryRun({ username: 'ada@example.com' }); // already registered\n// after\nawait dryRun({ username: 'ada+new@example.com' }); // unused email","handlingStrategy":"try-catch","validationCode":"// Pre-check uniqueness client-side if an API exists, else verify the account doesn't exist\nconst known = await lookupUserByEmail(email); // optional pre-flight\nif (known) redirectToSignIn();","typeGuard":"const isUniqueError = (e) => e?.status === 403 || /already registered/i.test(e?.message ?? '');","tryCatchPattern":"try {\n    await dryRun({ username: email });\n} catch (e) {\n    if (isUniqueError(e)) { // email taken: offer sign-in / recovery\n        showRecoveryLink();\n    }\n}","preventionTips":["Use an email not previously associated with the instance","Offer account recovery instead of re-registration for known emails","Treat 403 from the dry-run as 'email taken' in the UI","Keep a local record of test accounts used on shared instances"],"tags":["self-registration","validation","email"],"backgroundTag":"conflicting-resource-already-exists","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}