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

The `times` option on `thenReturn`/`thenResolve`/`thenThrow`/`thenReject` controls how many calls a behavior applies to before being exhausted. `validateOptions` rejects any value `<= 0` with a `RangeError` because zero or negative occurrences are nonsensical and would produce an immediately-dead behavior that can never fire.

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 d568f8ce37)

Solutions

  1. Pass a positive integer (`times: 1` or more), or omit `times` for an indefinite behavior.
  2. Use the `*Once` variants (`thenReturnOnce`, etc.) when you want exactly one application.
  3. Guard dynamic `times` values: only set the option when the value is `>= 1`.

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 resolveTimes(n?: number): number | undefined {
  if (typeof n === 'number' && n <= 0) throw new RangeError('times must be > 0')
  return n
}
vi.when(spy).calledWith(1).thenReturn('a', { times: resolveTimes(maybeZero) })

Type guard

function isValidTimes(n: unknown): n is number | undefined {
  return n == null || (typeof n === 'number' && n > 0)
}

Prevention

When it happens

Trigger: Passing `{ times: 0 }` or a negative number (e.g. `{ times: -1 }`) to any `then*` method on a `vi.when` `calledWith` chain.

Common situations: Computing `times` from a variable that can be zero, off-by-one in a loop, or confusing `times` with a different option.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/7479ba237404a83f.json. Report an issue: GitHub.