{"record":{"id":"db196c71d80ad9c5","repo":"TechnitiumSoftware/DnsServer","slug":"maxstatfiledays-must-be-greater-than-or-equal-to-0","errorCode":null,"errorMessage":"MaxStatFileDays must be greater than or equal to 0.","messagePattern":"MaxStatFileDays must be greater than or equal to 0\\.","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/StatsManager.cs","lineNumber":1704,"sourceCode":"                {\n                    _enableInMemoryStats = value;\n\n                    if (_enableInMemoryStats)\n                    {\n                        _hourlyStatsCache.Clear();\n                        _dailyStatsCache.Clear();\n                    }\n                }\n            }\n        }\n\n        public int MaxStatFileDays\n        {\n            get { return _maxStatFileDays; }\n            set\n            {\n                if (value < 0)\n                    throw new ArgumentOutOfRangeException(nameof(MaxStatFileDays), \"MaxStatFileDays must be greater than or equal to 0.\");\n\n                _maxStatFileDays = value;\n\n                if (_maxStatFileDays == 0)\n                    _statsCleanupTimer.Change(Timeout.Infinite, Timeout.Infinite);\n                else\n                    _statsCleanupTimer.Change(STATS_CLEANUP_TIMER_INITIAL_INTERVAL, STATS_CLEANUP_TIMER_PERIODIC_INTERVAL);\n            }\n        }\n\n        #endregion\n\n        class HourlyStats\n        {\n            #region variables\n\n            public readonly static HourlyStats Empty = new HourlyStats();\n","sourceCodeStart":1686,"sourceCodeEnd":1722,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/StatsManager.cs#L1686-L1722","documentation":"Thrown by StatsManager.MaxStatFileDays setter when the assigned value is negative. MaxStatFileDays controls how many days of .stat files are retained; 0 disables cleanup entirely (the cleanup timer is stopped via Timeout.Infinite). Negative values have no meaning and are rejected before field assignment.","triggerScenarios":"Assigning StatsManager.MaxStatFileDays to a value < 0, reachable from the stats settings UI or any config/API path that restores the retention setting.","commonSituations":"Operator types a negative number into the retention field; a config parser supplies -1 as a sentinel that is not translated to 0; an unvalidated integer field from a config file.","solutions":["Use 0 to disable cleanup, or any positive integer for the number of days to retain.","Clamp the configured value to >= 0 in your UI/config layer before assigning.","Treat any incoming -1/None sentinel as 0 (cleanup disabled) at the boundary."],"exampleFix":"// before\nstatsManager.MaxStatFileDays = configuredDays; // configuredDays == -1\n\n// after\nstatsManager.MaxStatFileDays = Math.Max(0, configuredDays);","handlingStrategy":"validation","validationCode":"statsManager.MaxStatFileDays = Math.Max(0, configuredDays);","typeGuard":null,"tryCatchPattern":"try { statsManager.MaxStatFileDays = configuredDays; }\ncatch (ArgumentOutOfRangeException ex) when (ex.ParamName == nameof(statsManager.MaxStatFileDays))\n{ statsManager.MaxStatFileDays = 0; }","preventionTips":["Constrain the retention UI input to non-negative integers.","Translate any -1/None config sentinel to 0 (cleanup disabled) at the boundary."],"tags":["stats","validation","argument-range","retention","config"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}