{"record":{"id":"ff7a7971dbc33109","repo":"winsw/winsw","slug":"invalid-periodicity-type-periodicity","errorCode":null,"errorMessage":"invalid periodicity type: {Periodicity}","messagePattern":"invalid periodicity type: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/WinSW.Core/PeriodicRollingCalendar.cs","lineNumber":85,"sourceCode":"                    .AddMilliseconds(increment),\n\n            PeriodicityType.TOP_OF_SECOND =>\n                new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second)\n                    .AddSeconds(increment),\n\n            PeriodicityType.TOP_OF_MINUTE =>\n                new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0)\n                    .AddMinutes(increment),\n\n            PeriodicityType.TOP_OF_HOUR =>\n                new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0)\n                    .AddHours(increment),\n\n            PeriodicityType.TOP_OF_DAY =>\n                new DateTime(input.Year, input.Month, input.Day)\n                    .AddDays(increment),\n\n            _ => throw new Exception(\"invalid periodicity type: \" + this.Periodicity),\n        };\n\n        public PeriodicityType Periodicity { get; set; }\n\n        public bool ShouldRoll\n        {\n            get\n            {\n                var now = DateTime.Now;\n                if (now > this.nextRoll)\n                {\n                    this.currentRoll = now;\n                    this.nextRoll = this.NextTriggeringTime(now, this.period);\n                    return true;\n                }\n\n                return false;\n            }","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/winsw/winsw/blob/1d0ee4a91bad596d5e7e9c360f2b39ef54674674/src/WinSW.Core/PeriodicRollingCalendar.cs#L67-L103","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"<!-- before -->\n<log mode=\"roll-by-time\" pattern=\"\" />\n\n<!-- after -->\n<log mode=\"roll-by-time\" pattern=\"yyyyMMdd\" />","handlingStrategy":"validation","validationCode":"// Validate the date format before constructing the appender\nvar testCalendar = new PeriodicRollingCalendar(pattern, period);\ntestCalendar.Init();\nif (testCalendar.Periodicity == PeriodicRollingCalendar.PeriodicityType.ERRONEOUS)\n{\n    throw new ArgumentException(\n        $\"The date pattern '{pattern}' does not vary at any supported periodicity \" +\n        \"(millisecond, second, minute, hour, or day). Use a finer-grained format.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["logging","time-based-rolling","date-format","configuration"],"backgroundTag":null,"analyzedSha":"1d0ee4a91bad596d5e7e9c360f2b39ef54674674","analyzedAt":"2026-08-13T15:26:09.332Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}