{"record":{"id":"95b8a81b8142dc6c","repo":"TechnitiumSoftware/DnsServer","slug":"zone-signing-key-zsk-automatic-rollover-days-val","errorCode":null,"errorMessage":"Zone Signing Key (ZSK) automatic rollover days valid range is 0-365.","messagePattern":"Zone Signing Key \\(ZSK\\) automatic rollover days valid range is 0-365\\.","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/Dnssec/DnssecPrivateKey.cs","lineNumber":438,"sourceCode":"\n        public DateTime StateTransitionBy\n        { get { return _stateTransitionBy; } }\n\n        public DateTime StateTransitionByWithDelays\n        { get { return _stateTransitionBy.AddMilliseconds(PrimaryZone.DNSSEC_TIMER_PERIODIC_INTERVAL); } }\n\n        public bool IsRetiring\n        { get { return _isRetiring; } }\n\n        public ushort RolloverDays\n        {\n            get { return _rolloverDays; }\n            set\n            {\n                if (_keyType == DnssecPrivateKeyType.ZoneSigningKey)\n                {\n                    if (value > 365)\n                        throw new ArgumentOutOfRangeException(nameof(RolloverDays), \"Zone Signing Key (ZSK) automatic rollover days valid range is 0-365.\");\n\n                    switch (_state)\n                    {\n                        case DnssecPrivateKeyState.Generated:\n                        case DnssecPrivateKeyState.Published:\n                        case DnssecPrivateKeyState.Ready:\n                        case DnssecPrivateKeyState.Active:\n                            if (_isRetiring)\n                                throw new InvalidOperationException(\"Zone Signing Key (ZSK) automatic rollover cannot be set since it is set to retire.\");\n\n                            break;\n\n                        default:\n                            throw new InvalidOperationException(\"Zone Signing Key (ZSK) automatic rollover cannot be set due to invalid key state.\");\n                    }\n                }\n                else\n                {","sourceCodeStart":420,"sourceCodeEnd":456,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/Dnssec/DnssecPrivateKey.cs#L420-L456","documentation":"Thrown by the RolloverDays property setter on a Zone Signing Key (ZSK) when the value exceeds 365 days. The setter (DnssecPrivateKey.cs:438) only validates the upper bound for ZSKs and only after confirming _keyType is ZoneSigningKey, so this guards the auto-rollover scheduler interval. A value of 0 disables automatic rollover; anything from 1 to 365 schedules it.","triggerScenarios":"Assigning DnssecPrivateKey.RolloverDays to a value greater than 365 on a key whose _keyType == DnssecPrivateKeyType.ZoneSigningKey. Reachable from the DNSSEC settings UI or any API/serialzation path that restores RolloverDays.","commonSituations":"Operator types a multi-year rollover period into the web console; a config import from another DNS server supplies a value in months that is passed as days; an automated script sets RolloverDays from an unvalidated config field.","solutions":["Clamp the configured value to the supported 0-365 range before assigning: value 0 disables auto-rollover, 365 is the maximum.","If you need longer rollover cycles, set RolloverDays to 0 and schedule manual key rollover via the DNSSEC API.","Validate the input in your UI/config layer with an ArgumentOutOfRangeException-style range check so the user is told the bound before it reaches the setter."],"exampleFix":"// before\nkey.RolloverDays = requestedDays; // requestedDays == 730\n\n// after\nconst int MAX_ZSK_ROLLOVER_DAYS = 365;\nint days = Math.Clamp(requestedDays, 0, MAX_ZSK_ROLLOVER_DAYS);\nkey.RolloverDays = (ushort)days;","handlingStrategy":"validation","validationCode":"const int MAX_ZSK_ROLLOVER_DAYS = 365;\nif (key.KeyType == DnssecPrivateKeyType.ZoneSigningKey && requestedDays is > 365)\n    throw new ArgumentOutOfRangeException(nameof(requestedDays), \"ZSK rollover days must be 0-365.\");\nkey.RolloverDays = (ushort)Math.Clamp(requestedDays, 0, MAX_ZSK_ROLLOVER_DAYS);","typeGuard":null,"tryCatchPattern":"try { key.RolloverDays = (ushort)days; }\ncatch (ArgumentOutOfRangeException ex) when (ex.ParamName == nameof(key.RolloverDays))\n{ /* inform user of 0-365 bound */ }","preventionTips":["Constrain the UI input for rollover days to 0-365 with a numeric stepper.","Treat any value > 365 from external config as a config error, not a silent clamp."],"tags":["dnssec","zsk","rollover","validation","argument-range"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}