nopSolutions/nopCommerce · error · NopException

Cart is empty

Error message

Cart is empty

What it means

Thrown by PrepareAndValidateShoppingCartAndCheckoutAttributesAsync when the customer's shopping cart (loaded by type ShoppingCart and store) contains no items. An empty cart cannot produce an order, so this is the first sanity check in the PlaceOrder pipeline.

Source

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

    /// <summary>
    /// Prepare and validate shopping cart and checkout attributes
    /// </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 PrepareAndValidateShoppingCartAndCheckoutAttributesAsync(PlaceOrderContainer details, ProcessPaymentRequest processPaymentRequest, Currency currentCurrency)
    {
        //checkout attributes
        details.CheckoutAttributesXml = await _genericAttributeService.GetAttributeAsync<string>(details.Customer, NopCustomerDefaults.CheckoutAttributes, processPaymentRequest.StoreId);
        details.CheckoutAttributeDescription = await _checkoutAttributeFormatter.FormatAttributesAsync(details.CheckoutAttributesXml, details.Customer);

        //load shopping cart
        details.Cart = await _shoppingCartService.GetShoppingCartAsync(details.Customer, ShoppingCartType.ShoppingCart, processPaymentRequest.StoreId);

        if (!details.Cart.Any())
            throw new NopException("Cart is empty");

        //validate the entire shopping cart
        var warnings = await _shoppingCartService.GetShoppingCartWarningsAsync(details.Cart, details.CheckoutAttributesXml, true);
        if (warnings.Any())
            throw new NopException(warnings.Aggregate(string.Empty, (current, next) => $"{current}{next};"));

        //validate individual cart items
        foreach (var sci in details.Cart)
        {
            var product = await _productService.GetProductByIdAsync(sci.ProductId);

            var sciWarnings = await _shoppingCartService.GetShoppingCartItemWarningsAsync(details.Customer,
                sci.ShoppingCartType, product, processPaymentRequest.StoreId, sci.AttributesXml,
                sci.CustomerEnteredPrice, sci.RentalStartDateUtc, sci.RentalEndDateUtc, sci.Quantity, false, sci.Id);
            if (sciWarnings.Any())
                throw new NopException(sciWarnings.Aggregate(string.Empty, (current, next) => $"{current}{next};"));
        }

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Guard the payment submission with a client-side check that disables the button after first click and verifies cart count.
  2. In custom integrations, verify IShoppingCartService.GetShoppingCartAsync returns items before constructing the payment request.
  3. Ensure the StoreId on the ProcessPaymentRequest matches the store where cart items were added.
  4. Redirect users with an empty cart away from the payment page.

Example fix

// before: var result = await _orderProcessingService.PlaceOrderAsync(processPaymentRequest);
// after:
var cart = await _shoppingCartService.GetShoppingCartAsync(customer, ShoppingCartType.ShoppingCart, storeId);
if (!cart.Any())
    return; // or redirect to cart page
var result = await _orderProcessingService.PlaceOrderAsync(processPaymentRequest);
Defensive patterns

Strategy: validation

Validate before calling

// Before PlaceOrder, confirm the cart has items
var cart = await _shoppingCartService.GetShoppingCartAsync(
    customer, ShoppingCartType.ShoppingCart, storeId);
if (!cart.Any())
{
    _notificationService.ErrorNotification("Your cart is empty.");
    return RedirectToRoute("ShoppingCart");
}

Type guard

bool CartHasItems(IList<ShoppingCartItem> cart) => cart != null && cart.Count > 0;

Try / catch

try
{
    var result = await _orderProcessingService.PlaceOrderAsync(processPaymentRequest);
}
catch (NopException ex) when (ex.Message == "Cart is empty")
{
    return RedirectToRoute("ShoppingCart");
}

Prevention

When it happens

Trigger: PlaceOrder or ProcessPayment is invoked when the customer has no active shopping cart items for the current store. The cart was emptied (items purchased or removed) between the checkout review page and the payment submission. A programmatic payment request was created with a stale CustomerId or StoreId that doesn't match the cart.

Common situations: Double-click or double-submit of the payment button where the first request completes and empties the cart. Session timeout causing the cart reference to become stale. A custom integration building a ProcessPaymentRequest manually without ensuring cart items exist. Store-mismatch where the cart was created under one store and PlaceOrder runs under another.

Related errors


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