passbolt/passbolt_api · error · ForbiddenException

The email is already registered.

Error message

The email is already registered.

What it means

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.

Solutions

  1. Sign in with the existing account instead of registering again
  2. Use the account recovery / forgot password flow for the registered email
  3. Test the dry-run with a brand-new email address
  4. Check active users in the admin workspace to confirm which email is taken

Example fix

// before
await dryRun({ username: 'ada@example.com' }); // already registered
// after
await dryRun({ username: 'ada+new@example.com' }); // unused email
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check uniqueness client-side if an API exists, else verify the account doesn't exist
const known = await lookupUserByEmail(email); // optional pre-flight
if (known) redirectToSignIn();

Type guard

const isUniqueError = (e) => e?.status === 403 || /already registered/i.test(e?.message ?? '');

Try / catch

try {
    await dryRun({ username: email });
} catch (e) {
    if (isUniqueError(e)) { // email taken: offer sign-in / recovery
        showRecoveryLink();
    }
}

Prevention

When it happens

Trigger: POST /self-registration/dry-run (or the equivalent registration flow) with a username/email that already exists in the users table.

Common situations: 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.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/02daeb7e0f45be52. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/SelfRegistration/src/Service/DryRun/SelfRegistrationAbstractDryRunService.php:61

        return $this->settings;
    }

    /**
     * Check that the email is not assigned to a registered user.
     *
     * @param string $username Value to check
     * @return void
     * @throws \Cake\Http\Exception\ForbiddenException if the user is already registered
     */
    protected function checkEmailNotPreviouslyRegistered(string $username): void
    {
        /** @var \App\Model\Table\UsersTable $UsersTable */
        $UsersTable = TableRegistry::getTableLocator()->get('Users');
        $user = $UsersTable->buildEntity(compact('username'));
        $isUnique = $UsersTable->isUniqueUsername($user);

        if (!$isUnique) {
            throw new ForbiddenException(__('The email is already registered.'));
        }
    }

    /**
     * @inheritDoc
     */
    public function isSelfRegistrationOpen(): bool
    {
        $settings = $this->getSelfRegistrationSettingsInDB();

        return isset($settings['provider']);
    }
}

View on GitHub (pinned to 31c1bbc10f)