nopSolutions/nopCommerce · warning · Exception

Checkout.MinOrderPlacementInterval

Error message

Checkout.MinOrderPlacementInterval

What it means

Thrown during order placement (the checkout confirm flow) when IsMinimumOrderPlacementIntervalValidAsync returns false — i.e., the same customer is trying to place a second order within the configured MinimumOrderPlacementInterval window. The exception message is the localized resource 'Checkout.MinOrderPlacementInterval' (a customer-facing 'please wait' string). It is an anti-fraud/anti-double-submit throttle, not a data error.

Source

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

        //model
        var model = await _checkoutModelFactory.PrepareConfirmOrderModelAsync(cart);

        var isCaptchaSettingEnabled = await _customerService.IsGuestAsync(customer) &&
                                      _captchaSettings.Enabled && _captchaSettings.ShowOnCheckoutPageForGuests;

        //captcha validation for guest customers
        if (isCaptchaSettingEnabled && !captchaValid)
        {
            model.Warnings.Add(await _localizationService.GetResourceAsync("Common.WrongCaptchaMessage"));
            return View(model);
        }

        try
        {
            //prevent 2 orders being placed within an X seconds time frame
            if (!await IsMinimumOrderPlacementIntervalValidAsync(customer))
                throw new Exception(await _localizationService.GetResourceAsync("Checkout.MinOrderPlacementInterval"));

            //place order
            var processPaymentRequest = await _orderProcessingService.GetProcessPaymentRequestAsync();
            if (processPaymentRequest == null)
            {
                //Check whether payment workflow is required
                if (await _orderProcessingService.IsPaymentWorkflowRequiredAsync(cart))
                    return RedirectToRoute(NopRouteNames.Standard.CHECKOUT_PAYMENT_INFO);

                processPaymentRequest = new ProcessPaymentRequest();
            }

            processPaymentRequest.StoreId = store.Id;
            processPaymentRequest.CustomerId = customer.Id;
            processPaymentRequest.PaymentMethodSystemName = await _genericAttributeService.GetAttributeAsync<string>(customer,
                NopCustomerDefaults.SelectedPaymentMethodAttribute, store.Id);
            await _orderProcessingService.SetProcessPaymentRequestAsync(processPaymentRequest);
            var placeOrderResult = await _orderProcessingService.PlaceOrderAsync(processPaymentRequest);

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Disable the 'Place Order' button immediately after the first click to prevent double submission.
  2. Wait the configured MinimumOrderPlacementInterval (OrderSettings) and retry if the order genuinely did not go through.
  3. Lower MinimumOrderPlacementInterval in OrderSettings if legitimate fast repeat orders are being blocked.
  4. Confirm the first submission's result before retrying to avoid duplicate orders.

Example fix

// before
if (!await IsMinimumOrderPlacementIntervalValidAsync(customer))
    throw new Exception(await _localizationService.GetResourceAsync("Checkout.MinOrderPlacementInterval"));
// after (treat as warning, not a thrown exception)
if (!await IsMinimumOrderPlacementIntervalValidAsync(customer))
{
    model.Warnings.Add(await _localizationService.GetResourceAsync("Checkout.MinOrderPlacementInterval"));
    return View(model);
}
Defensive patterns

Strategy: validation

Validate before calling

// Check the interval client-side and disable the button after first click.
// Server-side, treat as a warning rather than throwing:
if (!await IsMinimumOrderPlacementIntervalValidAsync(customer))
{
    model.Warnings.Add(await _localizationService.GetResourceAsync("Checkout.MinOrderPlacementInterval"));
    return View(model);
}

Try / catch

// The placement try/catch surfaces this as an order warning; verify the first order succeeded before retrying.
catch (Exception ex) when (ex.Message.Contains("MinOrderPlacementInterval"))
{ /* show 'please wait' message */ }

Prevention

When it happens

Trigger: A customer submits the checkout confirm twice in quick succession (double-click, retry, or scripted) within the MinimumOrderPlacementInterval seconds. The second submission hits this guard and throws the localized interval message.

Common situations: Customer double-clicks the 'Place Order' button; network retry resubmits; automated/bot checkout testing fires rapidly; the interval setting is too high for legitimate fast repeat orders; frontend does not disable the button after first click.

Related errors


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