winsw/winsw · error · Exception
invalid periodicity type: {Periodicity}
Error message
invalid periodicity type: {Periodicity} What it means
Thrown by PeriodicRollingCalendar.NextTriggeringTime when the Periodicity property is not one of the five handled switch arms (TOP_OF_MILLISECOND through TOP_OF_DAY). DeterminePeriodicityType infers the periodicity by testing whether the date format string changes between epochs; if no format segment varies at any supported granularity it returns PeriodicityType.ERRONEOUS, which is not handled by the switch and falls through to the throw.
Source
Thrown at src/WinSW.Core/PeriodicRollingCalendar.cs:85
.AddMilliseconds(increment),
PeriodicityType.TOP_OF_SECOND =>
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second)
.AddSeconds(increment),
PeriodicityType.TOP_OF_MINUTE =>
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0)
.AddMinutes(increment),
PeriodicityType.TOP_OF_HOUR =>
new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0)
.AddHours(increment),
PeriodicityType.TOP_OF_DAY =>
new DateTime(input.Year, input.Month, input.Day)
.AddDays(increment),
_ => throw new Exception("invalid periodicity type: " + this.Periodicity),
};
public PeriodicityType Periodicity { get; set; }
public bool ShouldRoll
{
get
{
var now = DateTime.Now;
if (now > this.nextRoll)
{
this.currentRoll = now;
this.nextRoll = this.NextTriggeringTime(now, this.period);
return true;
}
return false;
}View on GitHub (pinned to 1d0ee4a91b)
Solutions
- Use a valid .NET date format string that varies at a supported granularity (e.g., 'yyyyMMdd' for daily, 'yyyyMMddHH' for hourly, 'yyyyMMddHHmm' for per-minute)
- Verify the pattern attribute exists and is non-empty on the <log mode="roll-by-time"> element
- Test the format string with DateTime.ToString to confirm it produces different output across at least one of the supported periodicity steps
Example fix
<!-- before --> <log mode="roll-by-time" pattern="" /> <!-- after --> <log mode="roll-by-time" pattern="yyyyMMdd" />
Defensive patterns
Strategy: validation
Validate before calling
// Validate the date format before constructing the appender
var testCalendar = new PeriodicRollingCalendar(pattern, period);
testCalendar.Init();
if (testCalendar.Periodicity == PeriodicRollingCalendar.PeriodicityType.ERRONEOUS)
{
throw new ArgumentException(
$"The date pattern '{pattern}' does not vary at any supported periodicity " +
"(millisecond, second, minute, hour, or day). Use a finer-grained format.");
} Prevention
- Test date format strings with DateTime.ToString before using them as log patterns
- Use well-known formats: 'yyyyMMdd' (daily), 'yyyyMMddHH' (hourly), 'yyyyMMddHHmm' (per-minute)
- Avoid constant or empty pattern strings on roll-by-time appenders
When it happens
Trigger: TimeBasedRollingLogAppender is configured with a pattern (date format) that DeterminePeriodicityType cannot map to any supported granularity — e.g., an empty string, a constant literal with no date tokens, or a format coarser than TOP_OF_DAY (like 'yyyy' which only varies yearly). Init() sets Periodicity to ERRONEOUS, and the first ShouldRoll check or NextTriggeringTime call hits the default arm.
Common situations: A log mode='roll-by-time' appender with a missing or invalid pattern attribute; a pattern string containing literal text but no .NET date format tokens; a pattern that only varies at a granularity finer than millisecond or coarser than day.
Related errors
- Time Based rolling policy is specified but no pattern can be
- Roll-Size-Time Based rolling policy is specified but no patt
- Roll-Size-Time Based rolling policy is specified but autoRol
- Roll-Size-Time Based rolling policy is specified but zipOlde
- Undefined logging mode: {LogMode}
AI-assisted analysis of winsw/winsw@1d0ee4a91b (2026-08-13).
Data as JSON: /api/errors/ff7a7971dbc33109.
Report an issue: GitHub.