nopSolutions/nopCommerce · critical · NopException

processPaymentResult is not available

Error message

processPaymentResult is not available

What it means

Thrown after the payment branch when processPaymentResult is still null. Both the payment-required branch (switch) and the skip-payment branch assign processPaymentResult, so this guard catches a logic regression where neither path produced a result object before SaveOrderDetailsAsync consumes it.

Source

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

                    throw new NopException("Payment method is not active");

                //payment type
                processPaymentResult = (await _paymentService.GetRecurringPaymentTypeAsync(processPaymentRequest.PaymentMethodSystemName)) switch
                {
                    RecurringPaymentType.NotSupported => throw new NopException("Recurring payments are not supported by selected payment method"),
                    RecurringPaymentType.Manual => await _paymentService.ProcessRecurringPaymentAsync(processPaymentRequest),
                    //payment is processed on payment gateway site, info about last transaction in paymentResult parameter
                    RecurringPaymentType.Automatic => paymentResult ?? new ProcessPaymentResult(),
                    _ => throw new NopException("Not supported recurring payment type"),
                };
            }
            else
            {
                processPaymentResult = paymentResult ?? new ProcessPaymentResult { NewPaymentStatus = PaymentStatus.Paid };
            }

            if (processPaymentResult == null)
                throw new NopException("processPaymentResult is not available");

            if (processPaymentResult.Success)
            {
                //save order details
                var order = await SaveOrderDetailsAsync(processPaymentRequest, processPaymentResult, details);

                foreach (var orderItem in await _orderService.GetOrderItemsAsync(details.InitialOrder.Id))
                {
                    //save item
                    var newOrderItem = new OrderItem
                    {
                        OrderItemGuid = Guid.NewGuid(),
                        OrderId = order.Id,
                        ProductId = orderItem.ProductId,
                        UnitPriceInclTax = orderItem.UnitPriceInclTax,
                        UnitPriceExclTax = orderItem.UnitPriceExclTax,
                        PriceInclTax = orderItem.PriceInclTax,
                        PriceExclTax = orderItem.PriceExclTax,

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Audit any custom edits to ProcessNextRecurringPaymentAsync to ensure every branch assigns processPaymentResult.
  2. Re-merge upstream changes if a recent nopCommerce update added a switch arm you missed.
  3. Add a unit test covering all payment branches to prevent regression.
Defensive patterns

Strategy: try-catch

Try / catch

try
{
    var errors = await _orderProcessingService.ProcessNextRecurringPaymentAsync(recurringPayment);
}
catch (NopException ex) when (ex.Message == "processPaymentResult is not available")
{
    _logger.LogCritical(ex, "Recurring payment {Id}: no processPaymentResult produced - logic regression.",
        recurringPayment.Id);
    throw; // surface to ops; this indicates a code bug, not transient failure
}

Prevention

When it happens

Trigger: A code path where the switch arms were extended/modified and none assigned processPaymentResult, or a refactor left an unhandled case. With stock code the only realistic trigger is a custom fork that introduces a branch forgetting the assignment.

Common situations: Custom modification of ProcessNextRecurringPaymentAsync adding a new payment scenario without assigning the result; partial merge of an upstream change; a plugin hooking into the flow and returning without setting the variable.

Related errors


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