devlooped/moq · error · ArgumentOutOfRangeException
ArgumentOutOfRangeException: callCountTo (invalid range…
Error message
ArgumentOutOfRangeException: callCountTo (invalid range bounds for Times.Between with Range.Exclusive)
What it means
For Times.Between with Range.Exclusive, when from and to differ by exactly 1 there is no integer strictly between them, so the call throws ArgumentOutOfRangeException named callCountTo. This is the 'empty exclusive range' check that complements the callCountFrom bounds check.
Solutions
- Use Range.Inclusive for adjacent bounds: Times.Between(2, 3, Range.Inclusive)
- Widen the exclusive bounds by one (Between(1, 4, Exclusive)) if exclusivity is truly required
- Validate to - from > 1 before calling with Range.Exclusive
Example fix
// before mock.Verify(m => m.Foo(), Times.Between(2, 3, Range.Exclusive)); // after mock.Verify(m => m.Foo(), Times.Between(2, 3, Range.Inclusive));
Defensive patterns
Strategy: validation
Validate before calling
if (to - from > 1)
mock.Verify(m => m.Foo(), Times.Between(from, to, Range.Exclusive));
else
mock.Verify(m => m.Foo(), Times.Between(from, to, Range.Inclusive)); Prevention
- Exclusive ranges need a gap: to - from >= 2
- Default to Range.Inclusive unless exclusivity is explicit
- Test boundary configurations of expected call counts
When it happens
Trigger: Times.Between(2, 3, Range.Exclusive), Times.Between(5, 6, Range.Exclusive) — any exclusive interval with to - from == 1 (after the from/to ordering checks pass).
Common situations: Translating inclusive requirements ('at least 2, at most 3') into Exclusive range by mistake; dynamic bounds that happen to be adjacent.
Related errors
- ArgumentOutOfRangeException: callCount
- ArgumentOutOfRangeException: callCount
- ArgumentOutOfRangeException: callCountFrom (invalid range…
- ArgumentOutOfRangeException: callCountFrom (invalid range…
- Delays have to be greater than zero to ensure an async…
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/5bffae911b216eac.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/Times.cs:124
/// Specifies that a mocked method should be invoked between
/// <paramref name="callCountFrom"/> and <paramref name="callCountTo"/> times.
/// </summary>
/// <param name="callCountFrom">The minimum number of times.</param>
/// <param name="callCountTo">The maximum number of times.</param>
/// <param name="rangeKind">The kind of range. See <see cref="Range"/>.</param>
/// <returns>An object defining the allowed number of invocations.</returns>
public static Times Between(int callCountFrom, int callCountTo, Range rangeKind)
{
if (rangeKind == Range.Exclusive)
{
if (callCountFrom <= 0 || callCountTo <= callCountFrom)
{
throw new ArgumentOutOfRangeException(nameof(callCountFrom));
}
if (callCountTo - callCountFrom == 1)
{
throw new ArgumentOutOfRangeException(nameof(callCountTo));
}
return new Times(Kind.BetweenExclusive, callCountFrom + 1, callCountTo - 1);
}
if (callCountFrom < 0 || callCountTo < callCountFrom)
{
throw new ArgumentOutOfRangeException(nameof(callCountFrom));
}
return new Times(Kind.BetweenInclusive, callCountFrom, callCountTo);
}
/// <summary>
/// Specifies that a mocked method should be invoked exactly
/// <paramref name="callCount"/> times.
/// </summary>
/// <param name="callCount">The times that a method or property can be called.</param>View on GitHub (pinned to 89a5be629c)