nopSolutions/nopCommerce · warning · NopException

Checkout.MinOrderSubtotalAmount

Error message

Checkout.MinOrderSubtotalAmount

What it means

Thrown when the cart subtotal is below the configured minimum order subtotal threshold (_orderSettings.MinOrderSubtotalAmount) and ValidateMinOrderSubtotalAmountAsync returns false. The message uses the localized resource 'Checkout.MinOrderSubtotalAmount' formatted with the threshold converted to the customer's currency. This enforces a minimum spend policy at order placement.

Source

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

            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};"));
        }

        //min totals validation
        if (!await ValidateMinOrderSubtotalAmountAsync(details.Cart))
        {
            var minOrderSubtotalAmount = await _currencyService.ConvertFromPrimaryStoreCurrencyAsync(_orderSettings.MinOrderSubtotalAmount, currentCurrency);
            throw new NopException(string.Format(await _localizationService.GetResourceAsync("Checkout.MinOrderSubtotalAmount"),
                await _priceFormatter.FormatPriceAsync(minOrderSubtotalAmount, true, false)));
        }

        if (!await ValidateMinOrderTotalAmountAsync(details.Cart))
        {
            var minOrderTotalAmount = await _currencyService.ConvertFromPrimaryStoreCurrencyAsync(_orderSettings.MinOrderTotalAmount, currentCurrency);
            throw new NopException(string.Format(await _localizationService.GetResourceAsync("Checkout.MinOrderTotalAmount"),
                await _priceFormatter.FormatPriceAsync(minOrderTotalAmount, true, false)));
        }
    }

    /// <summary>
    /// Prepare and validate billing address
    /// </summary>
    /// <param name="details">PlaceOrder container</param>
    /// <returns>A task that represents the asynchronous operation</returns>
    /// <exception cref="NopException">Validation problems</exception>
    protected virtual async Task PrepareAndValidateBillingAddressAsync(PlaceOrderContainer details)

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Increase the cart subtotal by adding items or removing discount codes that push it below the threshold.
  2. Review and adjust _orderSettings.MinOrderSubtotalAmount in admin (Configuration > Settings > Order settings) if the threshold is too high.
  3. Display the minimum order requirement prominently on the cart page before the customer proceeds to checkout.
  4. Set MinOrderSubtotalAmount to 0 if no minimum is desired.

Example fix

// before (admin): orderSettings.MinOrderSubtotalAmount = 50m; cart subtotal = 35m
// after: orderSettings.MinOrderSubtotalAmount = 0m;  // disable minimum
// or: customer adds more items to exceed 50m
Defensive patterns

Strategy: validation

Validate before calling

// Before PlaceOrder, check minimum subtotal
if (await ValidateMinOrderSubtotalAmountAsync(cart) == false)
{
    var minAmount = await _currencyService.ConvertFromPrimaryStoreCurrencyAsync(
        _orderSettings.MinOrderSubtotalAmount, currentCurrency);
    var formatted = await _priceFormatter.FormatPriceAsync(minAmount, true, false);
    _notificationService.ErrorNotification(
        string.Format(await _localizationService.GetResourceAsync("Checkout.MinOrderSubtotalAmount"), formatted));
    return RedirectToRoute("ShoppingCart");
}

Type guard

async Task<bool> MeetsMinSubtotalAsync(IShoppingCartService svc, IList<ShoppingCartItem> cart, decimal min) =>
    min <= 0 || (await svc.GetShoppingCartSubTotalAsync(cart)).subTotal >= min;

Try / catch

try
{
    var result = await _orderProcessingService.PlaceOrderAsync(processPaymentRequest);
}
catch (NopException ex) when (ex.Message.Contains("MinOrderSubtotal"))
{
    _notificationService.ErrorNotification(ex.Message);
    return RedirectToRoute("ShoppingCart");
}

Prevention

When it happens

Trigger: The store has MinOrderSubtotalAmount configured (e.g. $50) and the customer's cart subtotal (after item-level discounts but before order-level discounts) falls below it. The setting was increased after the customer added items. The subtotal calculation is affected by tax inclusion settings reducing the visible subtotal.

Common situations: Admin set a minimum order value to cover shipping/handling costs. A customer applies a discount code that brings the subtotal below the minimum. Tax display settings make the subtotal appear higher than the pre-tax subtotal used for validation. A B2B store with a minimum order requirement.

Related errors


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