nopSolutions/nopCommerce · critical · NopException

Initial order could not be loaded

Error message

Initial order could not be loaded

What it means

Thrown in ProcessNextRecurringPaymentAsync when _orderService.GetOrderByIdAsync(recurringPayment.InitialOrderId) returns null. The recurring payment references a seed order that no longer exists in the database, so nopCommerce cannot reconstruct the payment context (customer, items, totals) needed for the next cycle.

Solutions

  1. Restore the missing initial order from backup, or hard-delete the orphaned RecurringPayment record if the subscription is defunct.
  2. Audit order-deletion routines to cascade-clean RecurringPayment rows.
  3. Add a FK/data-integrity check so recurring payments cannot outlive their initial order.

Example fix

// before
await _orderService.DeleteOrderAsync(initialOrder); // leaves orphan recurring payment

// after
foreach (var rp in await _orderService.GetRecurringPaymentsByInitialOrderIdAsync(initialOrder.Id))
    rp.IsActive = false;
await _orderService.UpdateRecurringPaymentAsync(rp);
await _orderService.DeleteOrderAsync(initialOrder);
Defensive patterns

Strategy: validation

Validate before calling

var initialOrder = await _orderService.GetOrderByIdAsync(recurringPayment.InitialOrderId);
if (initialOrder is null)
{
    recurringPayment.IsActive = false; // orphaned - quarantine
    await _orderService.UpdateRecurringPaymentAsync(recurringPayment);
    _logger.LogWarning("Recurring payment {Id} references deleted initial order {OrderId}",
        recurringPayment.Id, recurringPayment.InitialOrderId);
    return Array.Empty<string>();
}

return await _orderProcessingService.ProcessNextRecurringPaymentAsync(recurringPayment);

Type guard

async Task<bool> InitialOrderExistsAsync(RecurringPayment rp)
    => await _orderService.GetOrderByIdAsync(rp.InitialOrderId) is not null;

Try / catch

try
{
    var errors = await _orderProcessingService.ProcessNextRecurringPaymentAsync(recurringPayment);
}
catch (NopException ex) when (ex.Message == "Initial order could not be loaded")
{
    recurringPayment.IsActive = false;
    await _orderService.UpdateRecurringPaymentAsync(recurringPayment);
    _logger.LogCritical(ex, "Orphaned recurring payment {Id}", recurringPayment.Id);
}

Prevention

When it happens

Trigger: The initial/seed order was hard-deleted from the Orders table while its RecurringPayment row remains; data corruption; restore from backup that missed the order; manual SQL deletion of orders without cleaning recurring payment records.

Common situations: Aggressive order cleanup scripts that delete orders but not related recurring payments; partial DB restore; buggy custom order-purge logic.

Related errors


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

Appendix: source

Thrown at src/Libraries/Nop.Services/Orders/OrderProcessingService.cs:1899

    /// Process next recurring payment
    /// </summary>
    /// <param name="recurringPayment">Recurring payment</param>
    /// <param name="paymentResult">Process payment result (info about last payment for automatic recurring payments)</param>
    /// <returns>
    /// A task that represents the asynchronous operation
    /// The task result contains the collection of errors
    /// </returns>
    public virtual async Task<IEnumerable<string>> ProcessNextRecurringPaymentAsync(RecurringPayment recurringPayment, ProcessPaymentResult paymentResult = null)
    {
        ArgumentNullException.ThrowIfNull(recurringPayment);

        try
        {
            if (!recurringPayment.IsActive)
                throw new NopException("Recurring payment is not active");

            var initialOrder = await _orderService.GetOrderByIdAsync(recurringPayment.InitialOrderId)
                               ?? throw new NopException("Initial order could not be loaded");

            var customer = await _customerService.GetCustomerByIdAsync(initialOrder.CustomerId)
                           ?? throw new NopException("Customer could not be loaded");

            if (await GetNextPaymentDateAsync(recurringPayment) is null)
                throw new NopException("Next payment date could not be calculated");

            //payment info
            var processPaymentRequest = new ProcessPaymentRequest
            {
                StoreId = initialOrder.StoreId,
                CustomerId = customer.Id,
                OrderGuid = Guid.NewGuid(),
                InitialOrder = initialOrder,
                RecurringCycleLength = recurringPayment.CycleLength,
                RecurringCyclePeriod = recurringPayment.CyclePeriod,
                RecurringTotalCycles = recurringPayment.TotalCycles
            };

View on GitHub (pinned to 64bdf2ff08)