{"record":{"id":"1da2a7c8f39ffa25","repo":"JeffreySu/WeiXinMPSDK","slug":"argumentoutofrangeexception-length-must-be-0","errorCode":null,"errorMessage":"ArgumentOutOfRangeException (length must be >= 0)","messagePattern":"ArgumentOutOfRangeException \\(length must be >= 0\\)","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/TenPayV3Util.cs","lineNumber":164,"sourceCode":"        /// 取时间戳生成随即数,替换交易单号中的后10位流水号\n        /// </summary>\n        /// <returns></returns>\n        public static UInt32 UnixStamp()\n        {\n            TimeSpan ts = SystemTime.Now - new DateTimeOffset(1970, 1, 1, 0, 0, 0, 0, TimeSpan.Zero);\n            return Convert.ToUInt32(ts.TotalSeconds);\n        }\n\n        /// <summary>\n        /// 取随机数\n        /// </summary>\n        /// <param name=\"length\"></param>\n        /// <returns></returns>\n        public static string BuildRandomStr(int length)\n        {\n            if (length < 0)\n            {\n                throw new ArgumentOutOfRangeException(nameof(length));\n            }\n\n            var result = new StringBuilder(length);\n            var randomByte = new byte[1];\n            const int UnbiasedUpperBound = 250;//最大的不大于 256 且可被 10 整除的数\n            using (var randomNumberGenerator = RandomNumberGenerator.Create())\n            {\n                for (var i = 0; i < length; i++)\n                {\n                    do\n                    {\n                        randomNumberGenerator.GetBytes(randomByte);\n                    }\n                    while (randomByte[0] >= UnbiasedUpperBound);\n\n                    result.Append((char)('0' + randomByte[0] % 10));\n                }\n            }","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/TenPayV3Util.cs#L146-L182","documentation":"TenPayV3Util.BuildRandomStr(length) generates a random numeric string of the given length. The library explicitly rejects negative lengths with ArgumentOutOfRangeException because StringBuilder and the generation loop cannot produce a negative-length string.","triggerScenarios":"Passing a negative int to BuildRandomStr, typically a computed length from a variable (e.g. length = str.Length where str is empty minus an offset) or a caller-supplied request parameter.","commonSituations":"Dynamic nonce generation where the length derives from user input or parsed config that ends up negative; copy-paste of code where a constant was meant.","solutions":["Clamp or validate the length before calling: if (length < 0) length = 0;","Trace where the negative value originates (usually an arithmetic mistake on an input) and fix the source","Use a fixed constant length (e.g. BuildRandomStr(32)) for payment nonces as TenPay docs require"],"exampleFix":"// before\nvar nonce = TenPayV3Util.BuildRandomStr(orderId.Length - 10);\n// after\nvar len = Math.Max(0, orderId.Length - 10);\nvar nonce = TenPayV3Util.BuildRandomStr(len);","handlingStrategy":"validation","validationCode":"if (length < 0) throw new ArgumentException(\"length must be >= 0\", nameof(length)); var nonce = TenPayV3Util.BuildRandomStr(length);","typeGuard":"static bool IsValidRandomLength(int length) => length >= 0;","tryCatchPattern":"try { nonce = TenPayV3Util.BuildRandomStr(len); } catch (ArgumentOutOfRangeException) { nonce = TenPayV3Util.BuildRandomStr(32); }","preventionTips":["Prefer fixed constant lengths for payment nonces","Never compute length from unvalidated user input"],"tags":["validation","argument","random"],"backgroundTag":"value-out-of-range","analyzedSha":"be573f6f94bdbf718dd5f6cdecb137fbc7ff651e","analyzedAt":"2026-09-12T10:01:50.733Z","contentChangedAt":"2026-09-12T10:01:50.733Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}