nopSolutions/nopCommerce · error · Exception

Checkout.Address.NotFound

Error message

Checkout.Address.NotFound

What it means

Thrown by OpcSaveBilling after the ?? null-coalescing operator when GetCustomerAddressAsync(customer.Id, billingAddressId) returns null. The client supplied a billing_address_id > 0 that does not map to an address owned by that customer. The message is the localized resource key 'Checkout.Address.NotFound' resolved through ILocalizationService. It signals stale/invalid address selection data, not a server error.

Source

Thrown at src/Presentation/Nop.Web/Controllers/CheckoutController.cs:1546

            var store = await _storeContext.GetCurrentStoreAsync();
            var cart = await _shoppingCartService.GetShoppingCartAsync(customer, ShoppingCartType.ShoppingCart, store.Id);

            if (!cart.Any())
                throw new Exception("Your cart is empty");

            if (!_orderSettings.OnePageCheckoutEnabled)
                throw new Exception("One page checkout is disabled");

            if (await _customerService.IsGuestAsync(customer) && !_orderSettings.AnonymousCheckoutAllowed)
                throw new Exception("Anonymous checkout is not allowed");

            _ = int.TryParse(form["billing_address_id"], out var billingAddressId);

            if (billingAddressId > 0)
            {
                //existing address
                var address = await _customerService.GetCustomerAddressAsync(customer.Id, billingAddressId)
                              ?? throw new Exception(await _localizationService.GetResourceAsync("Checkout.Address.NotFound"));

                customer.BillingAddressId = address.Id;
                await _customerService.UpdateCustomerAsync(customer);
            }
            else
            {
                if (await _customerService.IsGuestAsync(customer) && _taxSettings.EuVatEnabled && _taxSettings.EuVatEnabledForGuests)
                {
                    var warning = await SaveCustomerVatNumberAsync(model.VatNumber, customer);
                    if (!string.IsNullOrEmpty(warning))
                        ModelState.AddModelError("", warning);
                }

                //new address
                var newAddress = model.BillingNewAddress;

                //custom address attributes
                var customAttributes = await _addressAttributeParser.ParseCustomAttributesAsync(form, NopCommonDefaults.AddressAttributeControlName);

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Refresh the address dropdown from the customer's actual address book before submit.
  2. Drop billing_address_id from the post and submit as a new (ShippingNewAddress/BillingNewAddress) address.
  3. Verify the address id passed is one returned by GetAddressesByCustomerId for that customer.
  4. If migrating, remap legacy address IDs to new ones.

Example fix

// before: posting a stale id
form["billing_address_id"] = oldDeletedAddressId;
// after: validate against the address book before posting
var mine = await _customerService.GetAddressesByCustomerIdAsync(customer.Id);
if (!mine.Any(a => a.Id == billingAddressId)) { /* send 0 to create a new address */ }
Defensive patterns

Strategy: validation

Validate before calling

// Validate the chosen address id belongs to the customer before posting.
var owned = (await _customerService.GetAddressesByCustomerIdAsync(customer.Id)).Select(a => a.Id);
if (!owned.Contains(billingAddressId)) billingAddressId = 0; // fall back to new address

Try / catch

const data = await res.json();
if (data.error && /address/i.test(data.message)) {
  await refreshAddressBook(); // re-pull the customer's addresses
  selectFirstAddress();
}

Prevention

When it happens

Trigger: Client posts form['billing_address_id'] = <positive id> for an address that the customer does not own or that no longer exists (deleted, belongs to another account, post-migration ID mismatch). Happens when a stored address list is out of sync with the form.

Common situations: Customer deleted the address in another tab but the dropdown still lists it; address book migrated with new IDs while the page cache holds old IDs; address shared across merged accounts; tampered/curled request with an arbitrary id.

Related errors


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