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

  1. Query the database for the InitialOrder's ShippingAddressId and verify the Address record exists.
  2. If the address was deleted, restore it from backup or recreate it from the order's stored address snapshot.
  3. Run a referential integrity check: find orders whose ShippingAddressId has no matching Address record.
  4. If the order no longer needs shipping (e.g. digital goods re-fulfillment), set ShippingStatus to ShippingNotRequired.
  5. 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

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


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