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

  1. Ensure the customer completes the payment method selection step (OpcSelectPaymentMethod) before payment-info; redirect back if SelectedPaymentMethodAttribute is missing.
  2. Verify the selected payment plugin is installed and active for the current store/customer.
  3. 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

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


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