nopSolutions/nopCommerce · error · NopException

Customer billing address not set

Error message

Customer billing address not set

What it means

Thrown during cart details preparation when the customer has no billing address while on the payment method selection page. The plugin fetches the billing address via customer.BillingAddressId; if it is null or zero, the address record is missing, and placement is ButtonPlacement.PaymentMethod, this exception fires inside HandleFunctionAsync which converts it into the Error string of the returned tuple.

Source

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

    /// </returns>
    private async Task<CartDetails> PrepareCartDetailsAsync(ButtonPlacement placement, bool withShipping = true)
    {
        //get the primary store currency
        var currencyCode = (await _currencyService.GetCurrencyByIdAsync(_currencySettings.PrimaryStoreCurrencyId))?.CurrencyCode;
        if (string.IsNullOrEmpty(currencyCode))
            throw new NopException("Primary store currency not set");

        //get customer shopping cart
        var customer = await _workContext.GetCurrentCustomerAsync();
        var store = await _storeContext.GetCurrentStoreAsync();
        var cart = await _shoppingCartService.GetShoppingCartAsync(customer, ShoppingCartType.ShoppingCart, store.Id);
        if (!cart.Any())
            throw new NopException("Shopping cart is empty");

        //get billing address
        var billingAddress = await _addressService.GetAddressByIdAsync(customer.BillingAddressId ?? 0);
        if (placement == ButtonPlacement.PaymentMethod && billingAddress is null)
            throw new NopException("Customer billing address not set");

        var shippingIsRequired = await _shoppingCartService.ShoppingCartRequiresShippingAsync(cart);

        var details = new CartDetails
        {
            Placement = placement,
            CurrencyCode = currencyCode,
            Customer = customer,
            Store = store,
            Cart = cart.ToList(),
            BillingAddress = billingAddress,
            ShippingIsRequired = shippingIsRequired,
        };

        if (!withShipping)
            return details;

        //get shipping details

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Ensure the customer completes the billing address form before reaching the payment method selection page
  2. Check that customer.BillingAddressId has a value and the referenced address record exists before invoking the payment flow
  3. Redirect the customer to the billing address step if no billing address is set
  4. Verify no custom checkout flow is bypassing the billing address requirement

Example fix

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

// after
if (placement == ButtonPlacement.PaymentMethod &&
    (!customer.BillingAddressId.HasValue ||
     await _addressService.GetAddressByIdAsync(customer.BillingAddressId.Value) is null))
    return RedirectToRoute("CheckoutBillingAddress");
var details = await manager.PrepareCartDetailsAsync(placement);
Defensive patterns

Strategy: validation

Validate before calling

// Validate billing address exists before calling PrepareCartDetailsAsync
if (placement == ButtonPlacement.PaymentMethod)
{
    var billingAddressId = customer.BillingAddressId;
    if (!billingAddressId.HasValue || billingAddressId.Value == 0)
        return Error("Billing address required");
    var addr = await _addressService.GetAddressByIdAsync(billingAddressId.Value);
    if (addr is null)
        return Error("Billing address record not found");
}

Try / catch

// HandleFunctionAsync returns (Result, Error) tuples — check the Error field
var (result, error) = await manager.PrepareCartDetailsAsync(placement);
if (!string.IsNullOrEmpty(error))
{
    if (error == "Customer billing address not set")
        return RedirectToRoute("CheckoutBillingAddress");
    // handle other errors
}

Prevention

When it happens

Trigger: PrepareCartDetailsAsync is called with placement == ButtonPlacement.PaymentMethod and customer.BillingAddressId is null or resolves to a deleted/nonexistent address record (GetAddressByIdAsync returns null).

Common situations: Customer navigated directly to the payment method step without completing the billing address form; a previously saved address was deleted from the database; a checkout flow customization that skips the billing address step; guest checkout where the address was never captured.

Related errors


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