nopSolutions/nopCommerce · error · NopException
Product (Id={sci.ProductId}) cannot be loaded
Error message
Product (Id={sci.ProductId}) cannot be loaded What it means
Thrown by ShoppingCartService while validating recurring shipment schedules when GetProductByIdAsync(sci.ProductId) returns null. The cart item references a product that cannot be loaded from the database. This is a referential-integrity break: the ShoppingCartItem exists but its Product is missing, so recurring-cycle validation cannot read product.IsRecurring / cycle fields and aborts.
Source
Thrown at src/Libraries/Nop.Services/Orders/ShoppingCartService.cs:1945
/// <returns>
/// A task that represents the asynchronous operation
/// The task result contains the error (if exists); otherwise, empty string. Cycle length. Cycle period. Total cycles
/// </returns>
public virtual async Task<(string error, int cycleLength, RecurringProductCyclePeriod cyclePeriod, int totalCycles)> GetRecurringCycleInfoAsync(IList<ShoppingCartItem> shoppingCart)
{
var rezCycleLength = 0;
RecurringProductCyclePeriod rezCyclePeriod = 0;
var rezTotalCycles = 0;
int? cycleLength = null;
RecurringProductCyclePeriod? cyclePeriod = null;
int? totalCycles = null;
var conflictError = await _localizationService.GetResourceAsync("ShoppingCart.ConflictingShipmentSchedules");
foreach (var sci in shoppingCart)
{
var product = await _productService.GetProductByIdAsync(sci.ProductId) ?? throw new NopException($"Product (Id={sci.ProductId}) cannot be loaded");
if (!product.IsRecurring)
continue;
//cycle length
if (cycleLength.HasValue && cycleLength.Value != product.RecurringCycleLength)
return (conflictError, rezCycleLength, rezCyclePeriod, rezTotalCycles);
cycleLength = product.RecurringCycleLength;
//cycle period
if (cyclePeriod.HasValue && cyclePeriod.Value != product.RecurringCyclePeriod)
return (conflictError, rezCycleLength, rezCyclePeriod, rezTotalCycles);
cyclePeriod = product.RecurringCyclePeriod;
//total cycles
if (totalCycles.HasValue && totalCycles.Value != product.RecurringTotalCycles)
return (conflictError, rezCycleLength, rezCyclePeriod, rezTotalCycles);
totalCycles = product.RecurringTotalCycles;
View on GitHub (pinned to 64bdf2ff08)
Solutions
- Run a data-integrity check for cart items whose ProductId has no matching product and clean them up.
- Before cart operations, ensure products referenced by active cart items are not hard-deleted; prefer soft-delete/Hide or remove cart items on product delete.
- Fix the test/import to insert the Product in the same transaction as the cart item.
- Catch NopException around the recurring validation call, log sci.Id/ProductId, and remove the offending cart item with a user-facing message.
Example fix
// before
var (warnings, _, _, _) = await _shoppingCartService.GetRecurringCycleInfoAsync(cart);
// after
foreach (var sci in cart)
{
var p = await _productService.GetProductByIdAsync(sci.ProductId);
if (p is null)
{
await _shoppingCartService.DeleteShoppingCartItemAsync(sci.Id, ensureOnlyActiveCheckoutAttributes: false);
continue;
}
}
var (warnings, _, _, _) = await _shoppingCartService.GetRecurringCycleInfoAsync(cart); Defensive patterns
Strategy: validation
Validate before calling
foreach (var sci in cart)
{
var p = await _productService.GetProductByIdAsync(sci.ProductId);
if (p is null)
{
await _shoppingCartService.DeleteShoppingCartItemAsync(sci.Id, ensureOnlyActiveCheckoutAttributes: false);
cart = cart.Where(x => x.Id != sci.Id).ToList();
}
} Try / catch
try { await _shoppingCartService.GetRecurringCycleInfoAsync(cart); }
catch (NopException ex) when (ex.Message.Contains("cannot be loaded"))
{
// a cart item references a missing product; log and remove offending items
_logger.LogError(ex, "Cart references a missing product");
} Prevention
- Do not hard-delete products that cart items still reference; soft-delete or remove the cart items first.
- Run periodic integrity checks for cart items with no matching product.
- Seed products in the same transaction as cart items in tests.
When it happens
Trigger: Adding to / validating a cart that contains a ShoppingCartItem whose ProductId points to a deleted, purged, or non-existent product, while the cart is being checked for recurring-schedule conflicts. Reachable during AddToCart, cart validation, and checkout when a recurring product is involved.
Common situations: A product was deleted (soft/hard) but cart items still reference it; a botched import/migration; a test that seeds a cart item without the product; caching a stale ProductId after the product was removed.
Related errors
- Initial order could not be loaded
- Customer could not be loaded
- Shopping cart has no recurring items
- Picture cannot be loaded
- Video cannot be loaded
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/4d96b1eb766d6522.
Report an issue: GitHub.