nopSolutions/nopCommerce · error · Exception
Payment method is not selected
Error message
Payment method is not selected
What it means
Thrown in OpcSavePaymentInfo when the previously-selected payment method cannot be loaded. The code reads SelectedPaymentMethodAttribute from the customer's generic attributes; if it is null/empty or the system name does not resolve to a plugin, LoadPluginBySystemNameAsync returns null and the ?? operator throws.
Source
Thrown at src/Presentation/Nop.Web/Controllers/CheckoutController.cs:1978
var customer = await _workContext.GetCurrentCustomerAsync();
var store = await _storeContext.GetCurrentStoreAsync();
var cart = await _shoppingCartService.GetShoppingCartAsync(customer, ShoppingCartType.ShoppingCart, store.Id);
if (!cart.Any())
throw new Exception("Your cart is empty");
if (!_orderSettings.OnePageCheckoutEnabled)
throw new Exception("One page checkout is disabled");
if (await _customerService.IsGuestAsync(customer) && !_orderSettings.AnonymousCheckoutAllowed)
throw new Exception("Anonymous checkout is not allowed");
var paymentMethodSystemName = await _genericAttributeService.GetAttributeAsync<string>(customer,
NopCustomerDefaults.SelectedPaymentMethodAttribute, store.Id);
var paymentMethod = await _paymentPluginManager
.LoadPluginBySystemNameAsync(paymentMethodSystemName, customer, store.Id)
?? throw new Exception("Payment method is not selected");
var warnings = await paymentMethod.ValidatePaymentFormAsync(form);
foreach (var warning in warnings)
ModelState.AddModelError("", warning);
if (ModelState.IsValid)
{
await _orderProcessingService.SetProcessPaymentRequestAsync(await paymentMethod.GetPaymentInfoAsync(form));
var confirmOrderModel = await _checkoutModelFactory.PrepareConfirmOrderModelAsync(cart);
return Json(new
{
update_section = new UpdateSectionJsonModel
{
name = "confirm-order",
html = await RenderPartialViewToStringAsync("OpcConfirmOrder", confirmOrderModel)
},
goto_section = "confirm_order"
});
View on GitHub (pinned to 64bdf2ff08)
Solutions
- Ensure the customer completes the payment method selection step (OpcSelectPaymentMethod) before payment-info; redirect back if SelectedPaymentMethodAttribute is missing.
- Verify the selected payment plugin is installed and active for the current store/customer.
- Validate the attribute exists server-side before invoking the plugin manager and surface a clear redirect.
Example fix
// before
var paymentMethod = await _paymentPluginManager
.LoadPluginBySystemNameAsync(paymentMethodSystemName, customer, store.Id)
?? throw new Exception("Payment method is not selected");
// after
if (string.IsNullOrEmpty(paymentMethodSystemName))
return Json(new { error = 1, goto_section = "payment_method" });
var paymentMethod = await _paymentPluginManager
.LoadPluginBySystemNameAsync(paymentMethodSystemName, customer, store.Id);
if (paymentMethod == null)
return Json(new { error = 1, goto_section = "payment_method" }); Defensive patterns
Strategy: validation
Validate before calling
// Validate the stored payment method attribute before loading the plugin
var sysName = await _genericAttributeService.GetAttributeAsync<string>(customer, NopCustomerDefaults.SelectedPaymentMethodAttribute, store.Id);
if (string.IsNullOrWhiteSpace(sysName))
return Json(new { error = 1, goto_section = "payment_method" }); Type guard
static bool IsValidSystemName(string s) => !string.IsNullOrWhiteSpace(s) && s.Contains('.'); Try / catch
catch (Exception exc) when (exc.Message == "Payment method is not selected")
{
return Json(new { error = 1, goto_section = "payment_method" });
} Prevention
- Enforce step ordering in the OPC flow so payment-info cannot be reached without payment-method selection.
- Use distributed session/generic-attribute storage in load-balanced setups so selection persists.
- Clear stale SelectedPaymentMethodAttribute when a payment plugin is uninstalled.
When it happens
Trigger: Customer reaches payment-info step without having selected a payment method first (SelectedPaymentMethodAttribute is null), or the selected method's plugin was uninstalled/disabled between selection and payment-info submission (line ~1978).
Common situations: Customer skipped/back-navigated past the payment method selection step; the generic attribute was never saved due to an earlier error; the payment plugin was removed by an admin; OPC flow state lost on session restart.
Related errors
- Selected payment method can't be parsed
- One page checkout is disabled
- Anonymous checkout is not allowed
- Checkout.Address.NotFound
- Shipping is not required
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/b43e9dbb260250ab.
Report an issue: GitHub.