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
- Audit any custom edits to ProcessNextRecurringPaymentAsync to ensure every branch assigns processPaymentResult.
- Re-merge upstream changes if a recent nopCommerce update added a switch arm you missed.
- 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 customising ProcessNextRecurringPaymentAsync, ensure every branch assigns processPaymentResult.
- Re-merge upstream changes after upgrades to catch newly added switch arms.
- Add unit tests covering each payment branch so a missing assignment fails CI.
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
- Not supported recurring payment type
- Recurring payments are not supported by selected payment met
- Payment method couldn't be loaded
- Payment method is not active
- Recurring payment is not active
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/5daac309c4cb4c8e.
Report an issue: GitHub.