nopSolutions/nopCommerce · error · NopException

Shipping total couldn't be calculated

Error message

Shipping total couldn't be calculated

What it means

Thrown when IOrderTotalCalculationService.GetShoppingCartShippingTotalsAsync returns null for either the tax-inclusive or tax-exclusive shipping total. This means the shipping rate computation engine could not produce a quote for the cart's selected shipping option, making it impossible to finalize the order's shipping cost.

Source

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

        details.OrderSubTotalInclTax = subTotalWithoutDiscountInclTax;
        details.OrderSubTotalDiscountInclTax = discountAmountInclTax;

        //discount history
        foreach (var disc in appliedDiscounts)
        {
            if (!_discountService.ContainsDiscount(details.AppliedDiscounts, disc))
                details.AppliedDiscounts.Add(disc);
        }

        //sub total (excl tax)
        details.OrderSubTotalExclTax = subTotalWithoutDiscountExclTax;
        details.OrderSubTotalDiscountExclTax = discountAmountExclTax;

        //shipping total
        var (orderShippingTotalInclTax, orderShippingTotalExclTax, _, shippingTotalDiscounts) = await _orderTotalCalculationService.GetShoppingCartShippingTotalsAsync(details.Cart);

        if (!orderShippingTotalInclTax.HasValue || !orderShippingTotalExclTax.HasValue)
            throw new NopException("Shipping total couldn't be calculated");

        details.OrderShippingTotalInclTax = orderShippingTotalInclTax.Value;
        details.OrderShippingTotalExclTax = orderShippingTotalExclTax.Value;

        foreach (var disc in shippingTotalDiscounts)
        {
            if (!_discountService.ContainsDiscount(details.AppliedDiscounts, disc))
                details.AppliedDiscounts.Add(disc);
        }

        //payment total
        var paymentAdditionalFee = await _paymentService.GetAdditionalHandlingFeeAsync(details.Cart, processPaymentRequest.PaymentMethodSystemName);
        details.PaymentAdditionalFeeInclTax = (await _taxService.GetPaymentMethodAdditionalFeeAsync(paymentAdditionalFee, true, details.Customer)).price;
        details.PaymentAdditionalFeeExclTax = (await _taxService.GetPaymentMethodAdditionalFeeAsync(paymentAdditionalFee, false, details.Customer)).price;

        //tax amount
        SortedDictionary<decimal, decimal> taxRatesDictionary;
        (details.OrderTaxTotal, taxRatesDictionary) = await _orderTotalCalculationService.GetTaxTotalAsync(details.Cart);

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Verify at least one shipping rate computation method is installed and active (Configuration > Shipping > Providers).
  2. Re-select a shipping option on the checkout shipping step so the SelectedShippingOptionAttribute is refreshed.
  3. Check the active shipping plugin's configuration (weight brackets, total brackets, geographic zones) covers the destination address.
  4. Ensure cart items have weights assigned if using a weight-based provider.
  5. Enable the TaxSettings and verify shipping tax calculation doesn't return null due to a missing tax provider.

Example fix

// before: no active shipping provider, customer session has stale shipping option
// after: configure a shipping provider, force re-selection:
await _genericAttributeService.SaveAttributeAsync(customer,
    NopCustomerDefaults.SelectedShippingOptionAttribute, null, storeId);
Defensive patterns

Strategy: validation

Validate before calling

// Before PlaceOrder, verify a shipping quote is available
var shippingOption = await _genericAttributeService
    .GetAttributeAsync<ShippingOption>(customer,
        NopCustomerDefaults.SelectedShippingOptionAttribute, storeId);
if (shippingOption == null)
{
    // no option selected; redirect to shipping step
    return RedirectToRoute("CheckoutShippingAddress");
}
// Optionally re-query rates to confirm they're still valid
var (inclTax, exclTax, _, _) = await _orderTotalCalculationService
    .GetShoppingCartShippingTotalsAsync(cart);
if (!inclTax.HasValue || !exclTax.HasValue)
{
    _notificationService.ErrorNotification("Shipping to your address is unavailable.");
    return RedirectToRoute("CheckoutShippingMethod");
}

Type guard

bool ShippingTotalsAvailable(decimal? inclTax, decimal? exclTax) =>
    inclTax.HasValue && exclTax.HasValue;

Try / catch

try
{
    var result = await _orderProcessingService.PlaceOrderAsync(processPaymentRequest);
}
catch (NopException ex) when (ex.Message == "Shipping total couldn't be calculated")
{
    // clear stale shipping option and redirect
    await _genericAttributeService.SaveAttributeAsync<ShippingOption>(customer,
        NopCustomerDefaults.SelectedShippingOptionAttribute, null, storeId);
    _notificationService.ErrorNotification("Please re-select a shipping method.");
    return RedirectToRoute("CheckoutShippingMethod");
}

Prevention

When it happens

Trigger: No shipping rate computation method is active/installed, the selected shipping option has no matching rate, the shipping address is in a zone not covered by any active provider, the cart weight/dimensions exceed configured limits, or the selected shipping option's generic attribute is stale after the provider was uninstalled.

Common situations: Fresh install where no shipping plugin is configured. The shipping provider was disabled in admin but the customer's session still references a now-invalid ShippingOption. Cart total weight is 0 or exceeds the provider's max weight. ShippingByTotal or ShippingByWeight plugin misconfigured. The 'Free shipping over X' setting combined with a shipping method that returns null when the threshold logic fails.

Related errors


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