nopSolutions/nopCommerce · error · Exception

One page checkout is disabled

Error message

One page checkout is disabled

What it means

Thrown by the OpcSaveBilling action when _orderSettings.OnePageCheckoutEnabled is false, yet a one-page-checkout (OPC) AJAX POST was received. nopCommerce guards every OPC step with this check so a store running multi-page checkout cannot be driven through OPC endpoints. The message is a hardcoded English literal returned inside the JSON error payload { error=1, message }. It indicates a configuration/flow mismatch, not a malformed request.

Source

Thrown at src/Presentation/Nop.Web/Controllers/CheckoutController.cs:1535

    [HttpPost]
    public virtual async Task<IActionResult> OpcSaveBilling(CheckoutBillingAddressModel model, IFormCollection form)
    {
        try
        {
            //validation
            if (_orderSettings.CheckoutDisabled)
                throw new Exception(await _localizationService.GetResourceAsync("Checkout.Disabled"));

            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");

            _ = int.TryParse(form["billing_address_id"], out var billingAddressId);

            if (billingAddressId > 0)
            {
                //existing address
                var address = await _customerService.GetCustomerAddressAsync(customer.Id, billingAddressId)
                              ?? throw new Exception(await _localizationService.GetResourceAsync("Checkout.Address.NotFound"));

                customer.BillingAddressId = address.Id;
                await _customerService.UpdateCustomerAsync(customer);
            }
            else
            {
                if (await _customerService.IsGuestAsync(customer) && _taxSettings.EuVatEnabled && _taxSettings.EuVatEnabledForGuests)

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Enable OnePageCheckoutEnabled in admin (Order settings) if OPC is the intended flow.
  2. If OPC is intentionally off, ensure clients never call OpcSaveBilling: redirect the OPC page to the standard BillingAddress action.
  3. Purge output/CDN cache so browsers stop posting to OPC endpoints after the setting flipped.
  4. If a custom theme hardcodes OPC AJAX calls, switch it to the multi-page controller flow.

Example fix

// before (admin Order settings)
orderSettings.OnePageCheckoutEnabled = false;
// after
orderSettings.OnePageCheckoutEnabled = true; // enables OpcSaveBilling/OpcSaveShipping/etc.
Defensive patterns

Strategy: validation

Validate before calling

// Client: only render/submit the OPC billing step when OPC is on.
const settings = await fetch('/api/checkout-settings').then(r => r.json());
if (!settings.onePageCheckoutEnabled) { location.href = '/checkout/billingaddress'; return; }

Try / catch

// The controller wraps the action in try/catch and returns JSON; handle it.
const res = await fetch('/Checkout/OpcSaveBilling', { method:'POST', body });
const data = await res.json();
if (data.error) {
  if (data.message === 'One page checkout is disabled') location.href = '/checkout/billingaddress';
  else showUserError(data.message);
}

Prevention

When it happens

Trigger: A client POSTs to the OpcSaveBilling billing step while _orderSettings.OnePageCheckoutEnabled == false. Typical when an admin disabled OPC but a shopper's stale browser tab still renders the OPC UI, or a custom integration calls OpcSaveBilling directly against a multi-page-checkout store.

Common situations: Admin toggled 'One page checkout enabled' off (Configuration > Order settings); a theme deployed that defaults to standard multi-page checkout; CDN/page cache still serving the old OPC page after the switch; integration tests calling OPC endpoints after a config change.

Related errors


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