{"id":"c6bce63cfd6ce87c","repo":"jestjs/jest","slug":"expectedargument-must-be-a-positive-integer","errorCode":null,"errorMessage":"${expectedArgument} must be a positive integer","messagePattern":"(.+?) must be a positive integer","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/expect/src/spyMatchers.ts","lineNumber":969,"sourceCode":"  [number, ...Array<unknown>]\n> =>\n  function (received: any, nth, ...expected): SyncExpectationResult {\n    const expectedArgument = 'n';\n    const options: MatcherHintOptions = {\n      expectedColor: (arg: string) => arg,\n      isNot: this.isNot,\n      promise: this.promise,\n      secondArgument: '...expected',\n    };\n    ensureMockOrSpy(\n      received,\n      'toHaveBeenNthCalledWith',\n      expectedArgument,\n      options,\n    );\n\n    if (!Number.isSafeInteger(nth) || nth < 1) {\n      throw new Error(\n        matcherErrorMessage(\n          matcherHint(\n            'toHaveBeenNthCalledWith',\n            undefined,\n            expectedArgument,\n            options,\n          ),\n          `${expectedArgument} must be a positive integer`,\n          printWithType(expectedArgument, nth, stringify),\n        ),\n      );\n    }\n\n    const receivedIsSpy = isSpy(received);\n    const receivedName = receivedIsSpy ? 'spy' : received.getMockName();\n\n    const calls = receivedIsSpy\n      ? received.calls.all().map((x: any) => x.args)","sourceCodeStart":951,"sourceCodeEnd":987,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/expect/src/spyMatchers.ts#L951-L987","documentation":"Thrown by `toHaveBeenNthCalledWith` (spyMatchers.ts:950) when the `n` argument (the 1-based call index) is not a positive safe integer. The matcher indexes into `mock.calls[nth - 1]`, so values like 0, -1, 1.5, NaN, Infinity, or a string would produce invalid indexing. Jest uses `Number.isSafeInteger(nth) && nth >= 1` as the gate and renders the message with `expectedArgument = 'n'`, so the rendered message reads `n must be a positive integer`.","triggerScenarios":"Calling `expect(fn).toHaveBeenNthCalledWith(0, ...)` (zero is invalid — calls are 1-indexed), `.toHaveBeenNthCalledWith(-1, ...)`, `.toHaveBeenNthCalledWith(1.5, ...)`, `.toHaveBeenNthCalledWith('1', ...)` (string), `.toHaveBeenNthCalledWith(NaN, ...)`, or `.toHaveBeenNthCalledWith(calls.length, ...)` intending the last call (off-by-one — should be `calls.length` for the Nth, which is correct, but `calls.length - 1` would be off).","commonSituations":"Off-by-one errors assuming 0-based indexing; passing a computed index from `findIndex` (0-based) directly instead of adding 1; dynamic index from config that defaulted to 0; porting from a custom matcher that was 0-based.","solutions":["Use 1-based indexing: the first call is `n = 1`, not 0.","If deriving from `findIndex`, add 1: `.toHaveBeenNthCalledWith(idx + 1, ...)`.","For the last call, prefer `toHaveBeenLastCalledWith(...)` to avoid index math.","Validate `n` is a positive integer before the assertion if it is dynamic."],"exampleFix":"// before\nconst idx = mock.calls.findIndex(c => c[0] === 'x');\nexpect(mock).toHaveBeenNthCalledWith(idx, 'x', payload);\n\n// after\nconst idx = mock.calls.findIndex(c => c[0] === 'x');\nexpect(mock).toHaveBeenNthCalledWith(idx + 1, 'x', payload);","handlingStrategy":"validation","validationCode":"if (!Number.isSafeInteger(n) || n < 1) {\n  throw new Error(`n must be a positive integer, got ${n}`);\n}\nexpect(fn).toHaveBeenNthCalledWith(n, ...args);","typeGuard":"const isPositiveInteger = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isSafeInteger(v) && v >= 1;","tryCatchPattern":"try {\n  expect(fn).toHaveBeenNthCalledWith(n, ...args);\n} catch (e) {\n  if (e instanceof Error && /must be a positive integer/.test(e.message)) {\n    console.error('n was', n, '(calls are 1-indexed)');\n  }\n  throw e;\n}","preventionTips":["Remember calls are 1-indexed: the first call is `n = 1`.","Add 1 to results of `findIndex` before passing as `n`.","Prefer `toHaveBeenLastCalledWith` when targeting the final call."],"tags":["jest","expect","validation","assertion","spy","mock","off-by-one"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}