{"record":{"id":"55bc21f8a0f1eaa4","repo":"nopSolutions/nopCommerce","slug":"error","errorCode":null,"errorMessage":"{error}","messagePattern":"\\{error\\}","errorType":"exception","errorClass":"NopException","httpStatus":null,"severity":"error","filePath":"src/Plugins/Nop.Plugin.Payments.PayPalCommerce/Services/PayPalCommerceServiceManager.cs","lineNumber":1655,"sourceCode":"            var details = await PrepareCartDetailsAsync(placement);\n\n            var savedPaymentToken = await _tokenService.GetByIdAsync(cardId ?? 0);\n            if (savedPaymentToken is not null && savedPaymentToken.CustomerId != details.Customer.Id)\n                throw new NopException(\"Card details not found\");\n\n            var isGuest = await _customerService.IsGuestAsync(details.Customer);\n            var isRecurring = await _shoppingCartService.ShoppingCartIsRecurringAsync(details.Cart);\n            if (isRecurring)\n            {\n                if (!settings.UseVault)\n                    throw new NopException(\"Vault disabled\");\n\n                if (isGuest)\n                    throw new NopException(\"Anonymous checkout disabled for recurring items\");\n\n                var (error, cycleLength, cyclePeriod, totalCycles) = await _shoppingCartService.GetRecurringCycleInfoAsync(details.Cart);\n                if (!string.IsNullOrEmpty(error))\n                    throw new NopException(error);\n            }\n\n            var paymentRequest = await _orderProcessingService.GetProcessPaymentRequestAsync();\n            var (order, _) = await GetCreatedOrderAsync(settings, paymentRequest, placement, details.ShippingIsRequired, paymentSource);\n            if (paymentRequest is null || order is null)\n                paymentRequest = new();\n\n            //prepare purchase unit\n            var purchaseUnit = await PreparePurchaseUnitAsync(settings, details, paymentRequest.OrderGuid.ToString());\n\n            //whether we should create a new order\n            if (order is null || isRecurring)\n            {\n                var isCard = string.Equals(paymentSource, nameof(PaymentSource.Card), StringComparison.InvariantCultureIgnoreCase);\n                var isVenmo = string.Equals(paymentSource, nameof(PaymentSource.Venmo), StringComparison.InvariantCultureIgnoreCase);\n                var isApplepay = string.Equals(paymentSource, nameof(PaymentSource.ApplePay), StringComparison.InvariantCultureIgnoreCase);\n                if (isRecurring && (isVenmo || isApplepay))\n                    throw new NopException($\"Payment source '{paymentSource.ToUpper()}' not supported\");","sourceCodeStart":1637,"sourceCodeEnd":1673,"githubUrl":"https://github.com/nopSolutions/nopCommerce/blob/64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2/src/Plugins/Nop.Plugin.Payments.PayPalCommerce/Services/PayPalCommerceServiceManager.cs#L1637-L1673","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the recurring product's cycle configuration (cycle length, cycle period, total cycles) in the admin product editor","Ensure all recurring items in the cart have compatible cycle periods (e.g., all daily or all monthly)","Verify cycle length and total cycles are positive integers","Log the specific error string returned by GetRecurringCycleInfoAsync to identify which item or setting is invalid"],"exampleFix":"// before\nvar (error, cycleLength, cyclePeriod, totalCycles) = await _shoppingCartService.GetRecurringCycleInfoAsync(details.Cart);\nif (!string.IsNullOrEmpty(error))\n    throw new NopException(error);\n\n// after\nvar (error, cycleLength, cyclePeriod, totalCycles) = await _shoppingCartService.GetRecurringCycleInfoAsync(details.Cart);\nif (!string.IsNullOrEmpty(error))\n{\n    await _logger.ErrorAsync($\"Recurring cycle validation failed for customer {details.Customer.Id}: {error}\");\n    throw new NopException($\"Recurring payment configuration error: {error}. Please verify product cycle settings.\");\n}","handlingStrategy":"validation","validationCode":"// Validate recurring cycle info before PayPal order creation\nvar isRecurring = await _shoppingCartService.ShoppingCartIsRecurringAsync(cart);\nif (isRecurring)\n{\n    var (cycleError, _, _, _) = await _shoppingCartService.GetRecurringCycleInfoAsync(cart);\n    if (!string.IsNullOrEmpty(cycleError))\n        return Error($\"Recurring product configuration issue: {cycleError}\");\n}","typeGuard":null,"tryCatchPattern":"var (order, error) = await manager.CreateOrderAsync(settings, placement, paymentSource, cardId, saveCard);\nif (!string.IsNullOrEmpty(error) && error.Contains(\"cycle\"))\n    return BadRequest($\"Recurring configuration error: {error}\");","preventionTips":["Validate recurring product cycle settings (length, period, total cycles) at product creation time","Prevent mixing incompatible recurring cycle periods in the same cart","Test recurring checkout flow after any product configuration change"],"tags":["recurring","cycle-configuration","validation","paypal-commerce","nopcommerce"],"backgroundTag":null,"analyzedSha":"64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2","analyzedAt":"2026-08-13T21:19:38.062Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}