nopSolutions/nopCommerce · warning · NopException

Account.EmailUsernameErrors.EmailAlreadyExists

Error message

Account.EmailUsernameErrors.EmailAlreadyExists

What it means

Thrown by SetEmailAsync when GetCustomerByEmailAsync(newEmail) finds another customer (different Id) already using that email, using localized resource 'Account.EmailUsernameErrors.EmailAlreadyExists'. Enforces email uniqueness across customers.

Source

Thrown at src/Libraries/Nop.Services/Customers/CustomerRegistrationService.cs:515

    public virtual async Task SetEmailAsync(Customer customer, string newEmail, bool requireValidation)
    {
        ArgumentNullException.ThrowIfNull(customer);

        if (newEmail == null)
            throw new NopException("Email cannot be null");

        newEmail = newEmail.Trim();
        var oldEmail = customer.Email;

        if (!CommonHelper.IsValidEmail(newEmail))
            throw new NopException(await _localizationService.GetResourceAsync("Account.EmailUsernameErrors.NewEmailIsNotValid"));

        if (newEmail.Length > 100)
            throw new NopException(await _localizationService.GetResourceAsync("Account.EmailUsernameErrors.EmailTooLong"));

        var customer2 = await _customerService.GetCustomerByEmailAsync(newEmail);
        if (customer2 != null && customer.Id != customer2.Id)
            throw new NopException(await _localizationService.GetResourceAsync("Account.EmailUsernameErrors.EmailAlreadyExists"));

        if (requireValidation)
        {
            //re-validate email
            customer.EmailToRevalidate = newEmail;
            await _customerService.UpdateCustomerAsync(customer);

            //email re-validation message
            await _genericAttributeService.SaveAttributeAsync(customer, NopCustomerDefaults.EmailRevalidationTokenAttribute, Guid.NewGuid().ToString());
            await _workflowMessageService.SendCustomerEmailRevalidationMessageAsync(customer, (await _workContext.GetWorkingLanguageAsync()).Id);
        }
        else
        {
            customer.Email = newEmail;
            await _customerService.UpdateCustomerAsync(customer);

            if (string.IsNullOrEmpty(oldEmail) || oldEmail.Equals(newEmail, StringComparison.InvariantCultureIgnoreCase))
                return;

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Pre-check uniqueness: call GetCustomerByEmailAsync before attempting the change and warn the user.
  2. If the duplicate is a stale/inactive account, delete or reassign it first so the email frees up.
  3. Catch the NopException at the UI layer and surface the localized message as a validation error.

Example fix

// before
await _customerRegistrationService.SetEmailAsync(customer, newEmail, requireValidation);

// after
var owner = await _customerService.GetCustomerByEmailAsync(newEmail);
if (owner is not null && owner.Id != customer.Id)
    ModelState.AddModelError(nameof(newEmail), "This email is already in use.");
else
    await _customerRegistrationService.SetEmailAsync(customer, newEmail, requireValidation);
Defensive patterns

Strategy: validation

Validate before calling

var owner = await _customerService.GetCustomerByEmailAsync(newEmail);
if (owner is not null && owner.Id != customer.Id)
    ModelState.AddModelError(nameof(newEmail), "Email already in use.");

Try / catch

try { await _customerRegistrationService.SetEmailAsync(customer, email, true); }
catch (NopException ex) { ModelState.AddModelError(nameof(email), ex.Message); }

Prevention

When it happens

Trigger: Calling SetEmailAsync with an email already claimed by a different customer account. The lookup is case-insensitive in the standard implementation, so case variations also collide.

Common situations: User trying to switch to an email they registered with on a second account; an admin reassigning an email that's taken; duplicate-account cleanup attempts.

Related errors


AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13). Data as JSON: /api/errors/b42f1fd4ee83ccb8. Report an issue: GitHub.