jestjs/jest · error · Error
must be a positive integer
Error message
${expectedArgument} must be a positive integer What it means
Thrown by `toHaveBeenNthCalledWith` (spyMatchers.ts:968) when the `nth` argument is not a safe positive integer. The matcher checks `Number.isSafeInteger(nth) && nth >= 1` because call indices are 1-based; zero, negatives, NaN, Infinity, fractions, and non-numbers are all invalid.
Solutions
- Use 1-based indexing: the first call is nth=1, not nth=0.
- If deriving from a 0-based index, add 1: toHaveBeenNthCalledWith(i + 1, ...).
- Ensure nth is a safe integer (not NaN/Infinity/fraction) before the call.
- For the last call prefer toHaveBeenLastCalledWith; for the only call just toHaveBeenCalledWith.
Example fix
// before expect(fn).toHaveBeenNthCalledWith(0, 'first'); expect(fn).toHaveBeenNthCalledWith(i, args); // i is 0-based // after expect(fn).toHaveBeenNthCalledWith(1, 'first'); expect(fn).toHaveBeenNthCalledWith(i + 1, args);
Defensive patterns
Strategy: validation
Validate before calling
const nth = index;
if (!Number.isSafeInteger(nth) || nth < 1) {
throw new Error('toHaveBeenNthCalledWith nth must be a positive integer (1-based)');
}
expect(fn).toHaveBeenNthCalledWith(nth, ...args); Type guard
const isPositiveInteger = (v: unknown): v is number => typeof v === 'number' && Number.isSafeInteger(v) && v >= 1;
Prevention
- Remember call indices are 1-based: first call is nth=1.
- Convert 0-based indices with +1 before the matcher.
- Prefer toHaveBeenLastCalledWith for the last call.
When it happens
Trigger: Calling `expect(fn).toHaveBeenNthCalledWith(0, ...)` (zero, not 1-based), a negative, a float like 1.5, NaN, a string like '1', undefined, or a computed index that is off-by-one against the 1-based convention.
Common situations: Off-by-one from assuming 0-based indexing (most common); a loop variable or array length used directly as nth; nth derived from a 0-based findIndex result without +1; passing an optional that was undefined.
Related errors
- path must not be an empty array
- value must be a mock or spy function
- value must be a mock function
- path must be a string or array
- value must be a function
AI-assisted analysis of jestjs/jest@8e6d128e4a (2026-08-10).
Data as JSON: /api/errors/c6bce63cfd6ce87c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/expect/src/spyMatchers.ts:969
[number, ...Array<unknown>]
> =>
function (received: any, nth, ...expected): SyncExpectationResult {
const expectedArgument = 'n';
const options: MatcherHintOptions = {
expectedColor: (arg: string) => arg,
isNot: this.isNot,
promise: this.promise,
secondArgument: '...expected',
};
ensureMockOrSpy(
received,
'toHaveBeenNthCalledWith',
expectedArgument,
options,
);
if (!Number.isSafeInteger(nth) || nth < 1) {
throw new Error(
matcherErrorMessage(
matcherHint(
'toHaveBeenNthCalledWith',
undefined,
expectedArgument,
options,
),
`${expectedArgument} must be a positive integer`,
printWithType(expectedArgument, nth, stringify),
),
);
}
const receivedIsSpy = isSpy(received);
const receivedName = receivedIsSpy ? 'spy' : received.getMockName();
const calls = receivedIsSpy
? received.calls.all().map((x: any) => x.args)View on GitHub (pinned to 8e6d128e4a)