nopSolutions/nopCommerce · error · NopException

Customer shipping address not set

Error message

Customer shipping address not set

What it means

Thrown during cart details preparation when shipping is required, the customer has no shipping address, and the placement is the payment method page. The plugin resolves the shipping address from customer.ShippingAddressId (or builds one from a pickup point); if none exists and shipping is mandatory, this fires.

Source

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

        //get shipping details
        details.ShippingOption = await _genericAttributeService
            .GetAttributeAsync<NopShippingOption>(customer, NopCustomerDefaults.SelectedShippingOptionAttribute, store.Id);
        details.PickupPoint = await _genericAttributeService
            .GetAttributeAsync<PickupPoint>(customer, NopCustomerDefaults.SelectedPickupPointAttribute, store.Id);
        details.IsPickup = _shippingSettings.AllowPickupInStore && details.PickupPoint is not null;
        details.ShippingAddress = details.IsPickup ? new NopAddress
        {
            Address1 = details.PickupPoint.Address,
            City = details.PickupPoint.City,
            County = details.PickupPoint.County,
            CountryId = (await _countryService.GetCountryByTwoLetterIsoCodeAsync(details.PickupPoint.CountryCode))?.Id,
            StateProvinceId = (await _stateProvinceService.GetStateProvinceByAbbreviationAsync(details.PickupPoint.StateAbbreviation,
                (await _countryService.GetCountryByTwoLetterIsoCodeAsync(details.PickupPoint.CountryCode))?.Id))?.Id,
            ZipPostalCode = details.PickupPoint.ZipPostalCode,
            CreatedOnUtc = DateTime.UtcNow
        } : await _addressService.GetAddressByIdAsync(customer.ShippingAddressId ?? 0);
        if (placement == ButtonPlacement.PaymentMethod && shippingIsRequired && details.ShippingAddress is null)
            throw new NopException("Customer shipping address not set");

        return details;
    }

    /// <summary>
    /// Prepare order context
    /// </summary>
    /// <param name="settings">Plugin settings</param>
    /// <param name="details">Shopping cart details</param>
    /// <param name="orderGuid">Order internal id</param>
    /// <param name="isApplePay">Apple Pay payment</param>
    /// <returns>Experience context</returns>
    private ExperienceContext PrepareOrderContext(PayPalCommerceSettings settings, CartDetails details, string orderGuid, bool isApplePay = false)
    {
        var protocol = _webHelper.GetCurrentRequestProtocol();

        var shippingPreference = ShippingPreferenceType.NO_SHIPPING.ToString().ToUpper();
        if (details.ShippingIsRequired)

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Ensure the customer selects a shipping address before reaching the payment method page when the cart contains shippable items
  2. Check that customer.ShippingAddressId has a value and the address record exists before invoking the payment flow
  3. Redirect to the shipping address step if the address is missing and the cart requires shipping
  4. Verify the cart's shipping requirement status is accurate (check product IsShipEnabled flags)

Example fix

// before
var details = await manager.PrepareCartDetailsAsync(placement);

// after
var requiresShipping = await _shoppingCartService.ShoppingCartRequiresShippingAsync(cart);
if (placement == ButtonPlacement.PaymentMethod && requiresShipping &&
    (!customer.ShippingAddressId.HasValue ||
     await _addressService.GetAddressByIdAsync(customer.ShippingAddressId.Value) is null))
    return RedirectToRoute("CheckoutShippingAddress");
var details = await manager.PrepareCartDetailsAsync(placement);
Defensive patterns

Strategy: validation

Validate before calling

// Validate shipping address exists when shipping is required
if (placement == ButtonPlacement.PaymentMethod)
{
    var requiresShipping = await _shoppingCartService.ShoppingCartRequiresShippingAsync(cart);
    if (requiresShipping)
    {
        var shippingAddressId = customer.ShippingAddressId;
        if (!shippingAddressId.HasValue || shippingAddressId.Value == 0)
            return Error("Shipping address required");
        var addr = await _addressService.GetAddressByIdAsync(shippingAddressId.Value);
        if (addr is null)
            return Error("Shipping address record not found");
    }
}

Try / catch

var (result, error) = await manager.PrepareCartDetailsAsync(placement);
if (!string.IsNullOrEmpty(error))
{
    if (error == "Customer shipping address not set")
        return RedirectToRoute("CheckoutShippingAddress");
}

Prevention

When it happens

Trigger: PrepareCartDetailsAsync is called with placement == ButtonPlacement.PaymentMethod, shippingIsRequired is true, the order is not a pickup, and customer.ShippingAddressId is null or resolves to a deleted/nonexistent address.

Common situations: Customer reached the payment step without selecting a shipping address; address record was deleted between steps; checkout flow customization that skips the shipping address step; cart contains shippable items but the shipping address form was never completed.

Related errors


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