nopSolutions/nopCommerce · error · NopException
Not supported cycle period
Error message
Not supported cycle period
What it means
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.
Source
Thrown at src/Libraries/Nop.Services/Orders/OrderProcessingService.cs:3282
return null;
var historyCollection = await _orderService.GetRecurringPaymentHistoryAsync(recurringPayment);
if (historyCollection.Count >= recurringPayment.TotalCycles)
return null;
//result
DateTime? result = null;
//calculate next payment date
if (historyCollection.Any())
{
result = recurringPayment.CyclePeriod switch
{
RecurringProductCyclePeriod.Days => recurringPayment.StartDateUtc.AddDays((double)recurringPayment.CycleLength * historyCollection.Count),
RecurringProductCyclePeriod.Weeks => recurringPayment.StartDateUtc.AddDays((double)(7 * recurringPayment.CycleLength) * historyCollection.Count),
RecurringProductCyclePeriod.Months => recurringPayment.StartDateUtc.AddMonths(recurringPayment.CycleLength * historyCollection.Count),
RecurringProductCyclePeriod.Years => recurringPayment.StartDateUtc.AddYears(recurringPayment.CycleLength * historyCollection.Count),
_ => throw new NopException("Not supported cycle period"),
};
}
else
{
if (recurringPayment.TotalCycles > 0)
result = recurringPayment.StartDateUtc;
}
return result;
}
/// <summary>
/// Gets the cycles remaining
/// </summary>
/// <param name="recurringPayment">Recurring payment</param>
/// <returns>A task that represents the asynchronous operation</returns>
public virtual async Task<int> GetCyclesRemainingAsync(RecurringPayment recurringPayment)
{
View on GitHub (pinned to 64bdf2ff08)
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.
Example fix
// before (creating a recurring payment)
recurringPayment.CyclePeriod = (RecurringProductCyclePeriod)someInt;
// after
if (!Enum.IsDefined(typeof(RecurringProductCyclePeriod), someInt))
throw new ArgumentException($"Invalid cycle period {someInt}");
recurringPayment.CyclePeriod = (RecurringProductCyclePeriod)someInt; Defensive patterns
Strategy: type-guard
Validate before calling
if (!Enum.IsDefined(typeof(RecurringProductCyclePeriod), recurringPayment.CyclePeriod))
throw new ArgumentException($"Invalid CyclePeriod {recurringPayment.CyclePeriod} on recurring payment {recurringPayment.Id}");
var next = await _orderProcessingService.GetNextPaymentDateAsync(recurringPayment); Type guard
static bool IsValidCyclePeriod(RecurringProductCyclePeriod p) =>
p == RecurringProductCyclePeriod.Days ||
p == RecurringProductCyclePeriod.Weeks ||
p == RecurringProductCyclePeriod.Months ||
p == RecurringProductCyclePeriod.Years; Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Shipping is required, but address is not available. Order ID
- 'Registered' role could not be loaded
- recurringCyclesError
- Billing address is not available
- Shipping address is not available
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/c4383d939b05ca03.
Report an issue: GitHub.