{"record":{"id":"559174c84c1c6840","repo":"TechnitiumSoftware/DnsServer","slug":"qpm-limit-value-cannot-be-less-than-0","errorCode":null,"errorMessage":"QPM limit value cannot be less than 0.","messagePattern":"QPM limit value cannot be less than 0\\.","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/DnsServer.cs","lineNumber":7421,"sourceCode":"            set\n            {\n                if (value is null)\n                {\n                    _qpmPrefixLimitsIPv4 = new Dictionary<int, (int, int)>();\n                }\n                else if (value.Count > byte.MaxValue)\n                {\n                    throw new ArgumentOutOfRangeException(nameof(QpmPrefixLimitsIPv4), \"QPM Prefix Limits for IPv4 cannot have more than 255 entries.\");\n                }\n                else\n                {\n                    foreach (KeyValuePair<int, (int, int)> qpmPrefixLimit in value)\n                    {\n                        if ((qpmPrefixLimit.Key < 0) || (qpmPrefixLimit.Key > 32))\n                            throw new ArgumentOutOfRangeException(nameof(QpmPrefixLimitsIPv4), \"QPM limit IPv4 prefix valid range is between 0 and 32.\");\n\n                        if ((qpmPrefixLimit.Value.Item1 < 0) || (qpmPrefixLimit.Value.Item2 < 0))\n                            throw new ArgumentOutOfRangeException(nameof(QpmPrefixLimitsIPv4), \"QPM limit value cannot be less than 0.\");\n                    }\n\n                    _qpmPrefixLimitsIPv4 = value;\n                }\n\n                ResetQpsLimitTimer();\n            }\n        }\n\n        public IReadOnlyDictionary<int, (int, int)> QpmPrefixLimitsIPv6\n        {\n            get { return _qpmPrefixLimitsIPv6; }\n            set\n            {\n                if (value is null)\n                {\n                    _qpmPrefixLimitsIPv6 = new Dictionary<int, (int, int)>();\n                }","sourceCodeStart":7403,"sourceCodeEnd":7439,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/DnsServer.cs#L7403-L7439","documentation":"Thrown by the QpmPrefixLimitsIPv4 property setter when any tuple value has Item1 (queries) or Item2 (limit) below 0. QPM limit values represent query counts and must be non-negative.","triggerScenarios":"Assigning QpmPrefixLimitsIPv4 a dictionary where any value tuple has a negative Item1 or Item2.","commonSituations":"Arithmetic producing a negative value when computing limits from a baseline; config file with a typo (e.g. negative number); default/uninitialized integer fields passed through.","solutions":["Ensure all QPM limit tuple values are >= 0.","Clamp computed values with Math.Max(0, value) before building the dictionary."],"exampleFix":"// before\nserver.QpmPrefixLimitsIPv4 =\n    new Dictionary<int,(int,int)> { { 24, (-5, 100) } }; // throws\n\n// after\nserver.QpmPrefixLimitsIPv4 =\n    new Dictionary<int,(int,int)> { { 24, (5, 100) } };","handlingStrategy":"validation","validationCode":"foreach (var kv in qpmV4)\n    if (kv.Value.Item1 < 0 || kv.Value.Item2 < 0)\n        throw new InvalidOperationException($\"Negative QPM value for prefix {kv.Key}\");\nserver.QpmPrefixLimitsIPv4 = qpmV4;","typeGuard":"static bool IsValidQpmValue((int,int) v) => v.Item1 >= 0 && v.Item2 >= 0;","tryCatchPattern":"try { server.QpmPrefixLimitsIPv4 = qpmV4; }\ncatch (ArgumentOutOfRangeException) { qpmV4 = qpmV4.Select(kv => (kv.Key, (Math.Max(0,kv.Value.Item1), Math.Max(0,kv.Value.Item2)))).ToDictionary(x=>x.Key,x=>x.Item2); server.QpmPrefixLimitsIPv4 = qpmV4; }","preventionTips":["Clamp computed rate values with Math.Max(0, value).","Validate tuple values before dictionary construction."],"tags":["dns","qpm","rate-limiting","validation"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}