nopSolutions/nopCommerce · error · NopException

{error}

Error message

{error}

What it means

Thrown in CreateOrderAsync when the cart has recurring items and GetRecurringCycleInfoAsync returns a non-empty error string. This wraps the underlying nopCommerce recurring payment validation error — the cycle length, period, or total cycles configuration is invalid or inconsistent for the items in the cart.

Source

Thrown at src/Plugins/Nop.Plugin.Payments.PayPalCommerce/Services/PayPalCommerceServiceManager.cs:1655

            var details = await PrepareCartDetailsAsync(placement);

            var savedPaymentToken = await _tokenService.GetByIdAsync(cardId ?? 0);
            if (savedPaymentToken is not null && savedPaymentToken.CustomerId != details.Customer.Id)
                throw new NopException("Card details not found");

            var isGuest = await _customerService.IsGuestAsync(details.Customer);
            var isRecurring = await _shoppingCartService.ShoppingCartIsRecurringAsync(details.Cart);
            if (isRecurring)
            {
                if (!settings.UseVault)
                    throw new NopException("Vault disabled");

                if (isGuest)
                    throw new NopException("Anonymous checkout disabled for recurring items");

                var (error, cycleLength, cyclePeriod, totalCycles) = await _shoppingCartService.GetRecurringCycleInfoAsync(details.Cart);
                if (!string.IsNullOrEmpty(error))
                    throw new NopException(error);
            }

            var paymentRequest = await _orderProcessingService.GetProcessPaymentRequestAsync();
            var (order, _) = await GetCreatedOrderAsync(settings, paymentRequest, placement, details.ShippingIsRequired, paymentSource);
            if (paymentRequest is null || order is null)
                paymentRequest = new();

            //prepare purchase unit
            var purchaseUnit = await PreparePurchaseUnitAsync(settings, details, paymentRequest.OrderGuid.ToString());

            //whether we should create a new order
            if (order is null || isRecurring)
            {
                var isCard = string.Equals(paymentSource, nameof(PaymentSource.Card), StringComparison.InvariantCultureIgnoreCase);
                var isVenmo = string.Equals(paymentSource, nameof(PaymentSource.Venmo), StringComparison.InvariantCultureIgnoreCase);
                var isApplepay = string.Equals(paymentSource, nameof(PaymentSource.ApplePay), StringComparison.InvariantCultureIgnoreCase);
                if (isRecurring && (isVenmo || isApplepay))
                    throw new NopException($"Payment source '{paymentSource.ToUpper()}' not supported");

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Check the recurring product's cycle configuration (cycle length, cycle period, total cycles) in the admin product editor
  2. Ensure all recurring items in the cart have compatible cycle periods (e.g., all daily or all monthly)
  3. Verify cycle length and total cycles are positive integers
  4. Log the specific error string returned by GetRecurringCycleInfoAsync to identify which item or setting is invalid

Example fix

// before
var (error, cycleLength, cyclePeriod, totalCycles) = await _shoppingCartService.GetRecurringCycleInfoAsync(details.Cart);
if (!string.IsNullOrEmpty(error))
    throw new NopException(error);

// after
var (error, cycleLength, cyclePeriod, totalCycles) = await _shoppingCartService.GetRecurringCycleInfoAsync(details.Cart);
if (!string.IsNullOrEmpty(error))
{
    await _logger.ErrorAsync($"Recurring cycle validation failed for customer {details.Customer.Id}: {error}");
    throw new NopException($"Recurring payment configuration error: {error}. Please verify product cycle settings.");
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate recurring cycle info before PayPal order creation
var isRecurring = await _shoppingCartService.ShoppingCartIsRecurringAsync(cart);
if (isRecurring)
{
    var (cycleError, _, _, _) = await _shoppingCartService.GetRecurringCycleInfoAsync(cart);
    if (!string.IsNullOrEmpty(cycleError))
        return Error($"Recurring product configuration issue: {cycleError}");
}

Try / catch

var (order, error) = await manager.CreateOrderAsync(settings, placement, paymentSource, cardId, saveCard);
if (!string.IsNullOrEmpty(error) && error.Contains("cycle"))
    return BadRequest($"Recurring configuration error: {error}");

Prevention

When it happens

Trigger: isRecurring is true, Vault is enabled, customer is registered, but GetRecurringCycleInfoAsync(details.Cart) returns a non-empty error string describing the specific recurring cycle problem.

Common situations: Recurring product has inconsistent cycle settings (e.g., cycle length of 0 or negative); mixed recurring products with incompatible cycle periods in the same cart; product's recurring settings were misconfigured in the admin; a product was changed from recurring to non-recurring while in a customer's cart.

Related errors


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