vitest-dev/vitest · error · RangeError
vi.when: `times` option must be greater than 0
Error message
vi.when: `times` option must be greater than 0
What it means
Thrown by `validateOptions` (called by each `then*`/`then*Once` builder) when the `times` option is a number less than or equal to zero. `times` controls how many calls a behavior applies to before being exhausted; zero or negative counts are nonsensical, so a RangeError is raised immediately at setup time rather than silently producing an always-exhausted behavior.
Solutions
- Use a positive integer: `times: 1` (or prefer `thenReturnOnce` for the single-call case).
- Guard dynamic counts: `times: Math.max(1, n)` or skip setting up the behavior when `n === 0`.
- Use `thenReturnOnce` instead of `times: 1` for clarity when you want exactly one application.
Example fix
// before
vi.when(spy).calledWith(1).thenReturn('a', { times: 0 })
// after
vi.when(spy).calledWith(1).thenReturnOnce('a') Defensive patterns
Strategy: validation
Validate before calling
function validTimes(n) {
if (typeof n === 'number' && n <= 0) throw new RangeError('times must be > 0')
return n
}
vi.when(spy).calledWith(1).thenReturn('a', { times: validTimes(n) }) Type guard
function isPositiveTimes(n): n is number {
return typeof n === 'number' && n > 0
} Prevention
- Prefer thenReturnOnce over { times: 1 } for single-shot behaviors.
- Guard dynamic counts with Math.max(1, n) or skip setup when n === 0.
- Validate computed times values before passing them to then* methods.
When it happens
Trigger: Calling `.thenReturn(value, { times: 0 })`, `.thenReturn(value, { times: -1 })`, or passing a computed `times` that underflows to zero/negative (e.g. `times: arr.length` on an empty array).
Common situations: Deriving `times` from a dynamic count (array length, counter) that can be zero; copy-paste of `times: 0` intending 'once' (should be `1` or `thenReturnOnce`); off-by-one in loop-driven stubbing.
Related errors
- All browser instances within a project must use the same…
- `bench.compare()` expects every argument to be the return…
- `bench.compare()` requires at least 2 benchmarks, received
- `bench()` expects a benchmark function. Call `bench(name…
- `bench.from()` expects a string path or a function…
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/7479ba237404a83f.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vitest/src/integrations/mock/when.ts:547
: `exhausted (${action.times} of ${action.times})`
}
return action.remaining === Number.POSITIVE_INFINITY
? 'never called'
: `${action.remaining} remaining (out of ${action.times})`
}
function getSymbol(action: BehaviorAction<unknown>): string {
if (hasBeenConsumed(action)) {
return '✓'
}
return '✗'
}
function validateOptions(options: BehaviorOptions | undefined) {
if (typeof options?.times === 'number' && options.times <= 0) {
throw new RangeError('vi.when: `times` option must be greater than 0')
}
}
View on GitHub (pinned to 1fa9837ec2)