{"record":{"id":"c0c1dc5e3bc3d88e","repo":"devlooped/moq","slug":"argumentoutofrangeexception-callcountfrom-invalid-range-c0c1dc","errorCode":null,"errorMessage":"ArgumentOutOfRangeException: callCountFrom (invalid range bounds for Times.Between with Range.Inclusive)","messagePattern":"ArgumentOutOfRangeException: callCountFrom \\(invalid range bounds for Times\\.Between with Range\\.Inclusive\\)","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Moq/Times.cs","lineNumber":132,"sourceCode":"        {\n            if (rangeKind == Range.Exclusive)\n            {\n                if (callCountFrom <= 0 || callCountTo <= callCountFrom)\n                {\n                    throw new ArgumentOutOfRangeException(nameof(callCountFrom));\n                }\n\n                if (callCountTo - callCountFrom == 1)\n                {\n                    throw new ArgumentOutOfRangeException(nameof(callCountTo));\n                }\n\n                return new Times(Kind.BetweenExclusive, callCountFrom + 1, callCountTo - 1);\n            }\n\n            if (callCountFrom < 0 || callCountTo < callCountFrom)\n            {\n                throw new ArgumentOutOfRangeException(nameof(callCountFrom));\n            }\n\n            return new Times(Kind.BetweenInclusive, callCountFrom, callCountTo);\n        }\n\n        /// <summary>\n        ///   Specifies that a mocked method should be invoked exactly\n        ///   <paramref name=\"callCount\"/> times.\n        /// </summary>\n        /// <param name=\"callCount\">The times that a method or property can be called.</param>\n        /// <returns>An object defining the allowed number of invocations.</returns>\n        public static Times Exactly(int callCount)\n        {\n            if (callCount < 0)\n            {\n                throw new ArgumentOutOfRangeException(nameof(callCount));\n            }\n","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/devlooped/moq/blob/89a5be629c752960fe403e95ff583e4ae6f00542/src/Moq/Times.cs#L114-L150","documentation":"Times.Between with Range.Inclusive requires from >= 0 and to >= from. When from is negative or greater than to, ArgumentOutOfRangeException named callCountFrom is thrown (the parameter deemed invalid is reported as callCountFrom for both order violations in this branch).","triggerScenarios":"Times.Between(-1, 5, Range.Inclusive) or Times.Between(5, 2, Range.Inclusive) — inverted or negative bounds.","commonSituations":"Swapping from/to arguments; computing bounds where a lower estimate exceeds the upper; negative sentinel values leaking in.","solutions":["Ensure 0 <= from <= to before calling; swap min/max of computed values with Math.Min/Math.Max","Use the Inclusive range when 0 should be allowed as a lower bound","Add a precondition check on the computed bounds"],"exampleFix":"// before\nmock.Verify(m => m.Foo(), Times.Between(max, min, Range.Inclusive));\n// after\nmock.Verify(m => m.Foo(), Times.Between(Math.Min(min, max), Math.Max(min, max), Range.Inclusive));","handlingStrategy":"validation","validationCode":"var lo = Math.Min(from, to);\nvar hi = Math.Max(from, to);\nif (lo >= 0)\n    mock.Verify(m => m.Foo(), Times.Between(lo, hi, Range.Inclusive));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Normalize bounds with Math.Min/Max before calling Between","Reject negative lower bounds early","Prefer Inclusive for literal translations of 'between x and y' requirements"],"tags":["argument-out-of-range","moq","verification"],"backgroundTag":"argument-out-of-range","analyzedSha":"89a5be629c752960fe403e95ff583e4ae6f00542","analyzedAt":"2026-09-16T05:31:39.496Z","contentChangedAt":"2026-09-16T05:31:39.496Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}