nopSolutions/nopCommerce · error · Exception
Shipping is not required
Error message
Shipping is not required
What it means
Thrown by OpcSaveShipping when ShoppingCartRequiresShippingAsync(cart) returns false, i.e. none of the cart items are shippable (all digital/downloadable, or IsShipEnabled/FreeShipping flags make shipping unnecessary). Because the shipping step is meaningless, nopCommerce aborts. Hardcoded literal message. It usually means the client navigated to a shipping step that shouldn't exist for this cart.
Source
Thrown at src/Presentation/Nop.Web/Controllers/CheckoutController.cs:1695
//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");
if (!await _shoppingCartService.ShoppingCartRequiresShippingAsync(cart))
throw new Exception("Shipping is not required");
//pickup point
if (_shippingSettings.AllowPickupInStore && !_orderSettings.DisplayPickupInStoreOnShippingMethodPage)
{
var pickupInStore = ParsePickupInStore(form);
if (pickupInStore)
{
var pickupOption = await ParsePickupOptionAsync(cart, form);
await SavePickupOptionAsync(pickupOption);
return await OpcLoadStepAfterShippingMethod(cart);
}
//set value indicating that "pick up in store" option has not been chosen
await _genericAttributeService.SaveAttributeAsync<PickupPoint>(customer, NopCustomerDefaults.SelectedPickupPointAttribute, null, store.Id);
}
_ = int.TryParse(form["shipping_address_id"], out var shippingAddressId);
View on GitHub (pinned to 64bdf2ff08)
Solutions
- Skip the OPC shipping step when the cart requires no shipping (the standard flow does this automatically).
- Verify product IsShipEnabled/IsDownload flags reflect intent.
- Recompute cart shipping requirement client-side before showing/submitting the step.
- Redirect to the next applicable step (payment) instead of calling OpcSaveShipping.
Example fix
// before: always posting shipping
await opc.saveShipping(...);
// after
const requiresShipping = await cartRequiresShipping();
if (!requiresShipping) { gotoPaymentStep(); return; }
await opc.saveShipping(...); Defensive patterns
Strategy: validation
Validate before calling
// Skip the shipping step entirely when shipping isn't required.
if (!await _shoppingCartService.ShoppingCartRequiresShippingAsync(cart))
return RedirectToRoute("CheckoutPaymentMethod"); Try / catch
if (data.error && /shipping is not required/i.test(data.message)) {
gotoPaymentStep();
} Prevention
- Compute shipping requirement before showing the shipping step.
- Re-check the requirement after cart edits.
- Don't render a shipping step for digital-only carts.
When it happens
Trigger: Cart contains only non-shippable items (downloads, digital goods) yet the client POSTs to OpcSaveShipping. Also when a previously shippable item was replaced by a non-shippable one mid-flow, or the cart was edited so shipping is no longer required.
Common situations: Mixed cart reduced to digital-only after a removal; theme always shows the shipping step regardless of cart contents; custom flow skips the shipping-required check; a downloadable product misconfigured as shippable was corrected.
Related errors
- Selected shipping method can't be parsed
- Selected shipping method can't be loaded
- One page checkout is disabled
- Anonymous checkout is not allowed
- Checkout.Address.NotFound
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/b5859ab297c5a057.
Report an issue: GitHub.