nopSolutions/nopCommerce · error · NopException

System customer account ({customer.SystemName}) could not be

Error message

System customer account ({customer.SystemName}) could not be deleted

What it means

Thrown by DeleteCustomerAsync as a NopException when customer.IsSystemAccount is true. Built-in system accounts (e.g., background task user, search-engine crawler user, admin-built-in) are protected from deletion to keep the platform functional.

Source

Thrown at src/Libraries/Nop.Services/Customers/CustomerService.cs:342

    /// </returns>
    public virtual async Task<Customer> GetShoppingCartCustomerAsync(IList<ShoppingCartItem> shoppingCart)
    {
        var customerId = shoppingCart.FirstOrDefault()?.CustomerId;

        return customerId.HasValue && customerId != 0 ? await GetCustomerByIdAsync(customerId.Value) : null;
    }

    /// <summary>
    /// Delete a customer
    /// </summary>
    /// <param name="customer">Customer</param>
    /// <returns>A task that represents the asynchronous operation</returns>
    public virtual async Task DeleteCustomerAsync(Customer customer)
    {
        ArgumentNullException.ThrowIfNull(customer);

        if (customer.IsSystemAccount)
            throw new NopException($"System customer account ({customer.SystemName}) could not be deleted");

        customer.Deleted = true;

        if (_customerSettings.SuffixDeletedCustomers)
        {
            if (!string.IsNullOrEmpty(customer.Email))
                customer.Email += NopCustomerServicesDefaults.CustomerDeletedSuffix;
            if (!string.IsNullOrEmpty(customer.Username))
                customer.Username += NopCustomerServicesDefaults.CustomerDeletedSuffix;
        }

        await _customerRepository.UpdateAsync(customer, false);
        await _customerRepository.DeleteAsync(customer);
    }

    /// <summary>
    /// Gets a customer
    /// </summary>

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Filter out system accounts before deleting: skip customers where IsSystemAccount == true.
  2. If the intent is to anonymize, soft-delete only non-system accounts (the method sets Deleted=true rather than physically removing).
  3. Review why a system account was targeted — usually indicates the batch query is too broad.

Example fix

// before
foreach (var c in customers)
    await _customerService.DeleteCustomerAsync(c);

// after
foreach (var c in customers.Where(x => !x.IsSystemAccount))
    await _customerService.DeleteCustomerAsync(c);
Defensive patterns

Strategy: validation

Validate before calling

foreach (var c in customers.Where(x => !x.IsSystemAccount))
    await _customerService.DeleteCustomerAsync(c);

Type guard

static bool IsDeletable(Customer c) => c is not null && !c.IsSystemAccount;

Prevention

When it happens

Trigger: Calling DeleteCustomerAsync on a customer whose IsSystemAccount flag is true — typically the built-in system/background accounts identified by a non-empty SystemName.

Common situations: A cleanup/maintenance script iterates all customers and tries to delete everyone; an admin attempts to remove a built-in account; a GDPR/anonymization batch not excluding system accounts.

Related errors


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