nopSolutions/nopCommerce · error · NopException

Anonymous checkout is not allowed

Error message

Anonymous checkout is not allowed

What it means

Thrown by PrepareAndValidateCustomerAsync during the standard PlaceOrder flow when the customer is a guest (IsGuestAsync returns true) and _orderSettings.AnonymousCheckoutAllowed is false. This enforces the store's policy on whether guest (non-registered) customers can complete purchases. If disabled, customers must register and log in before placing an order.

Source

Thrown at src/Libraries/Nop.Services/Orders/OrderProcessingService.cs:573

    /// <summary>
    /// Prepare and validate customer
    /// </summary>
    /// <param name="details">PlaceOrder container</param>
    /// <param name="processPaymentRequest">payment info holder</param>
    /// <param name="currentCurrency">The working currency</param>
    /// <returns>A task that represents the asynchronous operation</returns>
    /// <exception cref="NopException">Validation problems</exception>
    protected virtual async Task PrepareAndValidateCustomerAsync(PlaceOrderContainer details, ProcessPaymentRequest processPaymentRequest, Currency currentCurrency)
    {
        details.Customer = await _customerService.GetCustomerByIdAsync(processPaymentRequest.CustomerId);

        if (details.Customer == null)
            throw new ArgumentException("Customer is not set");

        //check whether customer is guest
        if (await _customerService.IsGuestAsync(details.Customer) && !_orderSettings.AnonymousCheckoutAllowed)
            throw new NopException("Anonymous checkout is not allowed");

        //customer currency
        var currencyTmp = await _currencyService.GetCurrencyByIdAsync(details.Customer.CurrencyId ?? 0);
        var customerCurrency = currencyTmp != null && currencyTmp.Published && await _storeMappingService.AuthorizeAsync(currencyTmp) ? currencyTmp : currentCurrency;
        var primaryStoreCurrency = await _currencyService.GetCurrencyByIdAsync(_currencySettings.PrimaryStoreCurrencyId);
        details.CustomerCurrencyCode = customerCurrency.CurrencyCode;
        details.CustomerCurrencyRate = customerCurrency.Rate / primaryStoreCurrency.Rate;

        //customer language
        details.CustomerLanguage = await _languageService.GetLanguageByIdAsync(details.Customer.LanguageId ?? 0);
        if (details.CustomerLanguage == null || !details.CustomerLanguage.Published || !await _storeMappingService.AuthorizeAsync(details.CustomerLanguage))
            details.CustomerLanguage = await _workContext.GetWorkingLanguageAsync();
    }

    /// <summary>
    /// Prepare details to place order based on the recurring payment.
    /// </summary>
    /// <param name="processPaymentRequest">Process payment request</param>

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Enable anonymous checkout in admin: Configuration > Settings > Order settings > 'Anonymous checkout allowed'.
  2. Require the customer to register/log in before reaching the payment step.
  3. Extend session timeout or implement a 'keep alive' to prevent mid-checkout authentication loss.
  4. In custom integrations, ensure the ProcessPaymentRequest.CustomerId refers to a registered (non-guest) customer.

Example fix

// before (admin): orderSettings.AnonymousCheckoutAllowed = false
// after: orderSettings.AnonymousCheckoutAllowed = true;
await _settingService.SaveSettingAsync(orderSettings, x => x.AnonymousCheckoutAllowed);
Defensive patterns

Strategy: validation

Validate before calling

// Before PlaceOrder, check guest + anonymous checkout policy
var customer = await _customerService.GetCustomerByIdAsync(processPaymentRequest.CustomerId);
if (await _customerService.IsGuestAsync(customer) && !_orderSettings.AnonymousCheckoutAllowed)
{
    _notificationService.ErrorNotification("Please register or log in to complete your order.");
    return RedirectToRoute("Login");
}

Type guard

async Task<bool> CanCheckoutAsync(ICustomerService svc, Customer c, bool anonAllowed) =>
    !await svc.IsGuestAsync(c) || anonAllowed;

Try / catch

try
{
    var result = await _orderProcessingService.PlaceOrderAsync(processPaymentRequest);
}
catch (NopException ex) when (ex.Message == "Anonymous checkout is not allowed")
{
    return RedirectToRoute("Login");
}

Prevention

When it happens

Trigger: A guest user (not logged in) attempts to check out while the 'Anonymous checkout allowed' setting is disabled in Order settings. The setting was changed from true to false after guest customers added items to their carts. A customer's session lost authentication and they reverted to guest status mid-checkout.

Common situations: B2B stores that require account registration. Admin disabled anonymous checkout to improve order tracking or comply with regulations. Session timeout caused an authenticated customer's session to expire, reverting them to guest status. A custom integration passing a guest CustomerId to PlaceOrder.

Related errors


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