{"id":"7479ba237404a83f","repo":"vitest-dev/vitest","slug":"vi-when-times-option-must-be-greater-than-0","errorCode":null,"errorMessage":"vi.when: `times` option must be greater than 0","messagePattern":"vi\\.when: `times` option must be greater than 0","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/integrations/mock/when.ts","lineNumber":547,"sourceCode":"      : `exhausted (${action.times} of ${action.times})`\n  }\n\n  return action.remaining === Number.POSITIVE_INFINITY\n    ? 'never called'\n    : `${action.remaining} remaining (out of ${action.times})`\n}\n\nfunction getSymbol(action: BehaviorAction<unknown>): string {\n  if (hasBeenConsumed(action)) {\n    return '✓'\n  }\n\n  return '✗'\n}\n\nfunction validateOptions(options: BehaviorOptions | undefined) {\n  if (typeof options?.times === 'number' && options.times <= 0) {\n    throw new RangeError('vi.when: `times` option must be greater than 0')\n  }\n}\n","sourceCodeStart":529,"sourceCodeEnd":550,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/integrations/mock/when.ts#L529-L550","documentation":"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.","triggerScenarios":"Passing `{ times: 0 }` or a negative number (e.g. `{ times: -1 }`) to any `then*` method on a `vi.when` `calledWith` chain.","commonSituations":"Computing `times` from a variable that can be zero, off-by-one in a loop, or confusing `times` with a different option.","solutions":["Pass a positive integer (`times: 1` or more), or omit `times` for an indefinite behavior.","Use the `*Once` variants (`thenReturnOnce`, etc.) when you want exactly one application.","Guard dynamic `times` values: only set the option when the value is `>= 1`."],"exampleFix":"// before\nvi.when(spy).calledWith(1).thenReturn('a', { times: 0 })\n// after\nvi.when(spy).calledWith(1).thenReturnOnce('a')","handlingStrategy":"validation","validationCode":"function resolveTimes(n?: number): number | undefined {\n  if (typeof n === 'number' && n <= 0) throw new RangeError('times must be > 0')\n  return n\n}\nvi.when(spy).calledWith(1).thenReturn('a', { times: resolveTimes(maybeZero) })","typeGuard":"function isValidTimes(n: unknown): n is number | undefined {\n  return n == null || (typeof n === 'number' && n > 0)\n}","tryCatchPattern":null,"preventionTips":["Use `*Once` variants for single-use behaviors instead of `{ times: 1 }`.","Guard dynamically computed `times` to only set the option when `>= 1`."],"tags":["mock","vi-when","range-error","validation"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}