nopSolutions/nopCommerce · error · NopException

Shopping cart total couldn't be calculated now

Error message

Shopping cart total couldn't be calculated now

What it means

Thrown when GetShoppingCartTotalAsync returns null for the cart total during order preparation on the payment method page. This happens when nopCommerce's order total calculation cannot produce a final total, typically due to complex discount/tax/rounding configurations. On product and cart pages the code falls back to subtotal, but on the payment method page it throws.

Source

Thrown at src/Plugins/Nop.Plugin.Payments.PayPalCommerce/Services/PayPalCommerceServiceManager.cs:557

    /// A task that represents the asynchronous operation
    /// The task result contains the order amount with breakdown
    /// </returns>
    private async Task<OrderMoney> PrepareOrderMoneyAsync(CartDetails details, List<Item> items)
    {
        //in some rare cases we need an additional item to adjust the order total
        //this can happen due to complex discounts or a large order and related to rounding in calculations
        //PayPal uses two decimal places, while nopCommerce can use more complex types of rounding (configured for each currency separately) 
        var adjustmentName = await _localizationService.GetResourceAsync("Plugins.Payments.PayPalCommerce.Order.Adjustment.Name");
        var adjustmentDescription = await _localizationService.GetResourceAsync("Plugins.Payments.PayPalCommerce.Order.Adjustment.Description");
        if (items.FirstOrDefault(item => adjustmentName.Equals(item.Name) && adjustmentDescription.Equals(item.Description)) is Item adjustmentItem)
            items.Remove(adjustmentItem);

        var (total, _, _, _, _, _) = await _orderTotalCalculationService
            .GetShoppingCartTotalAsync(details.Cart, usePaymentMethodAdditionalFee: false);
        if (total is null)
        {
            if (details.Placement == ButtonPlacement.PaymentMethod)
                throw new NopException("Shopping cart total couldn't be calculated now");

            //on product and cart pages the total is not yet calculated, so use subtotal here
            var (_, _, subTotal, _, _) = await _orderTotalCalculationService.GetShoppingCartSubTotalAsync(details.Cart, includingTax: false);
            total = subTotal;
        }
        var orderTotal = PrepareMoney(total.Value, details.CurrencyCode);

        var (shippingTotal, _, _) = await _orderTotalCalculationService
            .GetShoppingCartShippingTotalAsync(details.Cart, includingTax: _taxSettings.ShippingPriceIncludesTax);
        var orderShippingTotal = PrepareMoney(shippingTotal ?? decimal.Zero, details.CurrencyCode);

        var (taxTotal, _) = await _orderTotalCalculationService.GetTaxTotalAsync(details.Cart, usePaymentMethodAdditionalFee: false);
        var orderTaxTotal = PrepareMoney(taxTotal, details.CurrencyCode);

        var itemAdjustment = decimal.Zero;
        var itemTotal = items.Sum(item => ConvertMoney(item.UnitAmount) * int.Parse(item.Quantity));
        var discountTotal = itemTotal + ConvertMoney(orderTaxTotal) + ConvertMoney(orderShippingTotal) - ConvertMoney(orderTotal);
        if (discountTotal < decimal.Zero)

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Review active discount combinations for rounding conflicts; simplify or disable conflicting discount rules
  2. Check currency rounding configuration in nopCommerce (Configuration > Currencies) to ensure consistent decimal places
  3. Verify tax calculation settings do not produce null totals (Configuration > Tax Settings)
  4. Test the cart total calculation independently via GetShoppingCartTotalAsync to identify which configuration causes the null result
  5. If using custom discount or tax providers, verify their output is non-null for all cart combinations

Example fix

// before
var (total, _, _, _, _, _) = await _orderTotalCalculationService
    .GetShoppingCartTotalAsync(details.Cart, usePaymentMethodAdditionalFee: false);
if (total is null)
    throw new NopException("Shopping cart total couldn't be calculated now");

// after
var (total, _, _, _, _, _) = await _orderTotalCalculationService
    .GetShoppingCartTotalAsync(details.Cart, usePaymentMethodAdditionalFee: false);
if (total is null)
{
    //log details for diagnosis
    await _logger.InformationAsync($"Cart total was null for customer {details.Customer.Id}, placement {details.Placement}");
    var (_, _, subTotal, _, _) = await _orderTotalCalculationService
        .GetShoppingCartSubTotalAsync(details.Cart, includingTax: false);
    total = subTotal;
}
Defensive patterns

Strategy: fallback

Validate before calling

// Pre-check cart total calculation independently
var (testTotal, _, _, _, _, _) = await _orderTotalCalculationService
    .GetShoppingCartTotalAsync(cart, usePaymentMethodAdditionalFee: false);
if (testTotal is null && placement == ButtonPlacement.PaymentMethod)
{
    //investigate discount/tax configuration before proceeding
    _logger.Warning("Cart total returned null — check discount and tax configuration");
    return Error("Unable to calculate order total. Please review your discount and tax settings.");
}

Try / catch

var (order, error) = await manager.CreateOrderAsync(settings, placement, paymentSource, cardId, saveCard);
if (!string.IsNullOrEmpty(error))
{
    if (error.Contains("total couldn't be calculated"))
    {
        //guide user to simplify cart or contact support
        return View("CartTotalError");
    }
}

Prevention

When it happens

Trigger: PreparePurchaseUnitAsync calls GetShoppingCartTotalAsync with usePaymentMethodAdditionalFee=false, the result total is null, and details.Placement == ButtonPlacement.PaymentMethod.

Common situations: Complex discount combinations (e.g., percentage + fixed discounts on the same order) that cause rounding conflicts between nopCommerce's currency-specific rounding and PayPal's two-decimal-place requirement; tax calculation configuration that produces unresolvable totals; gift card or store credit that drives the total calculation to an indeterminate state.

Related errors


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