nopSolutions/nopCommerce · error · NopException
Shipping address is not available
Error message
Shipping address is not available
What it means
Thrown during the reorder/recurring-payment pipeline when the InitialOrder requires shipping (ShippingStatus != ShippingNotRequired) and is not pickup-in-store, but the ShippingAddressId is null or the referenced address record does not exist in the database. This is a data-integrity check ensuring the reorder has a deliverable destination.
Source
Thrown at src/Libraries/Nop.Services/Orders/OrderProcessingService.cs:663
details.CheckoutAttributeDescription = details.InitialOrder.CheckoutAttributeDescription;
//tax display type
details.CustomerTaxDisplayType = details.InitialOrder.CustomerTaxDisplayType;
//sub total
details.OrderSubTotalInclTax = details.InitialOrder.OrderSubtotalInclTax;
details.OrderSubTotalExclTax = details.InitialOrder.OrderSubtotalExclTax;
details.OrderSubTotalDiscountExclTax = details.InitialOrder.OrderSubTotalDiscountExclTax;
details.OrderSubTotalDiscountInclTax = details.InitialOrder.OrderSubTotalDiscountInclTax;
//shipping info
if (details.InitialOrder.ShippingStatus != ShippingStatus.ShippingNotRequired)
{
details.PickupInStore = details.InitialOrder.PickupInStore;
if (!details.PickupInStore)
{
if (!details.InitialOrder.ShippingAddressId.HasValue || await _addressService.GetAddressByIdAsync(details.InitialOrder.ShippingAddressId.Value) is not Address shippingAddress)
throw new NopException("Shipping address is not available");
//clone shipping address
details.ShippingAddress = _addressService.CloneAddress(shippingAddress);
if (await _countryService.GetCountryByAddressAsync(details.ShippingAddress) is Country shippingCountry && !shippingCountry.AllowsShipping)
throw new NopException($"Country '{shippingCountry.Name}' is not allowed for shipping");
}
else if (details.InitialOrder.PickupAddressId.HasValue && await _addressService.GetAddressByIdAsync(details.InitialOrder.PickupAddressId.Value) is Address pickupAddress)
details.PickupAddress = _addressService.CloneAddress(pickupAddress);
details.ShippingMethodName = details.InitialOrder.ShippingMethod;
details.ShippingRateComputationMethodSystemName = details.InitialOrder.ShippingRateComputationMethodSystemName;
details.ShippingStatus = ShippingStatus.NotYetShipped;
}
else
details.ShippingStatus = ShippingStatus.ShippingNotRequired;
//shipping total
details.OrderShippingTotalInclTax = details.InitialOrder.OrderShippingInclTax;
View on GitHub (pinned to 64bdf2ff08)
Solutions
- Query the database for the InitialOrder's ShippingAddressId and verify the Address record exists.
- If the address was deleted, restore it from backup or recreate it from the order's stored address snapshot.
- Run a referential integrity check: find orders whose ShippingAddressId has no matching Address record.
- If the order no longer needs shipping (e.g. digital goods re-fulfillment), set ShippingStatus to ShippingNotRequired.
- Prevent address deletion by adding a foreign key constraint or a pre-delete check for order references.
Example fix
// before: order.ShippingAddressId = 1234; Address 1234 deleted from DB // after: var address = await _addressService.InsertAddressAsync(restoredAddress); order.ShippingAddressId = address.Id; await _orderService.UpdateOrderAsync(order);
Defensive patterns
Strategy: validation
Validate before calling
// Before reorder, validate the initial order's shipping address exists
if (initialOrder.ShippingStatus != ShippingStatus.ShippingNotRequired
&& !initialOrder.PickupInStore)
{
if (!initialOrder.ShippingAddressId.HasValue)
{
_logger.LogError("Order {OrderId} has no shipping address ID", initialOrder.Id);
return;
}
var addr = await _addressService.GetAddressByIdAsync(initialOrder.ShippingAddressId.Value);
if (addr == null)
{
_logger.LogError("Order {OrderId} references deleted shipping address {AddressId}",
initialOrder.Id, initialOrder.ShippingAddressId);
return;
}
} Type guard
async Task<bool> ReorderShippingAddressValidAsync(
IAddressService addrSvc, Order o) =>
o.ShippingStatus == ShippingStatus.ShippingNotRequired
|| o.PickupInStore
|| (o.ShippingAddressId.HasValue
&& await addrSvc.GetAddressByIdAsync(o.ShippingAddressId.Value) != null); Try / catch
try
{
var result = await _orderProcessingService.ReOrderAsync(initialOrder, processPaymentRequest);
}
catch (NopException ex) when (ex.Message == "Shipping address is not available")
{
_logger.LogError(ex, "Reorder failed: shipping address missing for order {OrderId}", initialOrder.Id);
// restore address from backup or cancel the reorder
} Prevention
- Never hard-delete address records without checking for order references.
- Add a foreign key constraint on Order.ShippingAddressId to prevent orphaned references.
- Run periodic referential integrity audits: find orders whose ShippingAddressId has no matching Address.
- Before running reorder/recurring jobs, validate source orders have existing shipping address records.
- Implement soft-delete for addresses instead of hard-delete to preserve order history.
When it happens
Trigger: The InitialOrder's shipping address record was deleted from the Address table, the ShippingAddressId is null (corrupted or never set), or an async resolution returned null because the address was soft-deleted by a cleanup process. This is specific to the reorder path which re-reads the address by ID rather than from the customer.
Common situations: Database cleanup or GDPR-compliance scripts that deleted address records without nullifying order references. Data migration that failed to carry over shipping address records. Address records deleted via direct SQL or a custom plugin that bypassed referential integrity checks. An order created by a now-purged guest session.
Related errors
- Billing address is not available
- Shipping address is not provided
- Email is not valid
- recurringCyclesError
- Shipping total couldn't be calculated
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/5ecd25bccd4bbec8.
Report an issue: GitHub.