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

  1. 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)
  2. Verify the pattern attribute exists and is non-empty on the <log mode="roll-by-time"> element
  3. 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

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


AI-assisted analysis of winsw/winsw@1d0ee4a91b (2026-08-13). Data as JSON: /api/errors/ff7a7971dbc33109. Report an issue: GitHub.