{"record":{"id":"c4383d939b05ca03","repo":"nopSolutions/nopCommerce","slug":"not-supported-cycle-period","errorCode":null,"errorMessage":"Not supported cycle period","messagePattern":"Not supported cycle period","errorType":"exception","errorClass":"NopException","httpStatus":null,"severity":"error","filePath":"src/Libraries/Nop.Services/Orders/OrderProcessingService.cs","lineNumber":3282,"sourceCode":"            return null;\r\n\r\n        var historyCollection = await _orderService.GetRecurringPaymentHistoryAsync(recurringPayment);\r\n        if (historyCollection.Count >= recurringPayment.TotalCycles)\r\n            return null;\r\n\r\n        //result\r\n        DateTime? result = null;\r\n\r\n        //calculate next payment date\r\n        if (historyCollection.Any())\r\n        {\r\n            result = recurringPayment.CyclePeriod switch\r\n            {\r\n                RecurringProductCyclePeriod.Days => recurringPayment.StartDateUtc.AddDays((double)recurringPayment.CycleLength * historyCollection.Count),\r\n                RecurringProductCyclePeriod.Weeks => recurringPayment.StartDateUtc.AddDays((double)(7 * recurringPayment.CycleLength) * historyCollection.Count),\r\n                RecurringProductCyclePeriod.Months => recurringPayment.StartDateUtc.AddMonths(recurringPayment.CycleLength * historyCollection.Count),\r\n                RecurringProductCyclePeriod.Years => recurringPayment.StartDateUtc.AddYears(recurringPayment.CycleLength * historyCollection.Count),\r\n                _ => throw new NopException(\"Not supported cycle period\"),\r\n            };\r\n        }\r\n        else\r\n        {\r\n            if (recurringPayment.TotalCycles > 0)\r\n                result = recurringPayment.StartDateUtc;\r\n        }\r\n\r\n        return result;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Gets the cycles remaining\r\n    /// </summary>\r\n    /// <param name=\"recurringPayment\">Recurring payment</param>\r\n    /// <returns>A task that represents the asynchronous operation</returns>\r\n    public virtual async Task<int> GetCyclesRemainingAsync(RecurringPayment recurringPayment)\r\n    {\r","sourceCodeStart":3264,"sourceCodeEnd":3300,"githubUrl":"https://github.com/nopSolutions/nopCommerce/blob/64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2/src/Libraries/Nop.Services/Orders/OrderProcessingService.cs#L3264-L3300","documentation":"Thrown by OrderProcessingService in the CalculateNextPaymentDate path when recurringPayment.CyclePeriod does not match any of the known RecurringProductCyclePeriod values (Days, Weeks, Months, Years). It is an enum-exhaustiveness guard (the default arm of a switch expression). Hitting it means the persisted CyclePeriod value is outside the defined enum range, which should be impossible under normal data entry and signals corruption or an unsupported value.","triggerScenarios":"A RecurringPayment whose CyclePeriod is set to an integer that does not map to Days/Weeks/Months/Years, evaluated while computing the next payment date (historyCollection.Any()). Reachable via custom code that casts an arbitrary int to RecurringProductCyclePeriod, a corrupted row, or an enum value removed/renamed between versions.","commonSituations":"A migration or manual SQL that wrote an out-of-range CyclePeriod; a custom plugin casting an invalid int; a version upgrade where an enum member was removed but old rows still reference it; tests seeding bad data.","solutions":["Find and repair the offending RecurringPayment row: validate CyclePeriod is within the defined enum range (0-3 by default) and correct it.","Add input validation when creating recurring payments to reject out-of-range CyclePeriod values before persistence.","If you extended the enum, update this switch to handle the new members.","Catch NopException around recurring-payment processing and log the recurringPayment.Id for triage."],"exampleFix":"// before (creating a recurring payment)\nrecurringPayment.CyclePeriod = (RecurringProductCyclePeriod)someInt;\n\n// after\nif (!Enum.IsDefined(typeof(RecurringProductCyclePeriod), someInt))\n    throw new ArgumentException($\"Invalid cycle period {someInt}\");\nrecurringPayment.CyclePeriod = (RecurringProductCyclePeriod)someInt;","handlingStrategy":"type-guard","validationCode":"if (!Enum.IsDefined(typeof(RecurringProductCyclePeriod), recurringPayment.CyclePeriod))\n    throw new ArgumentException($\"Invalid CyclePeriod {recurringPayment.CyclePeriod} on recurring payment {recurringPayment.Id}\");\n\nvar next = await _orderProcessingService.GetNextPaymentDateAsync(recurringPayment);","typeGuard":"static bool IsValidCyclePeriod(RecurringProductCyclePeriod p) =>\n    p == RecurringProductCyclePeriod.Days ||\n    p == RecurringProductCyclePeriod.Weeks ||\n    p == RecurringProductCyclePeriod.Months ||\n    p == RecurringProductCyclePeriod.Years;","tryCatchPattern":null,"preventionTips":["Validate CyclePeriod with Enum.IsDefined before persisting a recurring payment.","Never cast arbitrary ints to RecurringProductCyclePeriod without validation.","If you extend the enum, update the switch in CalculateNextPaymentDate."],"tags":["recurring-payment","enum","switch","data-integrity"],"backgroundTag":null,"analyzedSha":"64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2","analyzedAt":"2026-08-13T21:19:38.062Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}