{"id":"b9ba1fc8fe4178a0","repo":"jestjs/jest","slug":"expected-value-must-be-a-non-negative-integer","errorCode":null,"errorMessage":"expected value must be a non-negative integer","messagePattern":"expected value must be a non-negative integer","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/jest-matcher-utils/src/index.ts","lineNumber":242,"sourceCode":"  options?: MatcherHintOptions,\n): void => {\n  ensureActualIsNumber(actual, matcherName, options);\n  ensureExpectedIsNumber(expected, matcherName, options);\n};\n\nexport const ensureExpectedIsNonNegativeInteger = (\n  expected: unknown,\n  matcherName: string,\n  options?: MatcherHintOptions,\n): void => {\n  if (\n    typeof expected !== 'number' ||\n    !Number.isSafeInteger(expected) ||\n    expected < 0\n  ) {\n    // Prepend maybe not only for backward compatibility.\n    const matcherString = (options ? '' : '[.not]') + matcherName;\n    throw new Error(\n      matcherErrorMessage(\n        matcherHint(matcherString, undefined, undefined, options),\n        `${EXPECTED_COLOR('expected')} value must be a non-negative integer`,\n        printWithType('Expected', expected, printExpected),\n      ),\n    );\n  }\n};\n\n// Given array of diffs, return concatenated string:\n// * include common substrings\n// * exclude change substrings which have opposite op\n// * include change substrings which have argument op\n//   with inverse highlight only if there is a common substring\nconst getCommonAndChangedSubstrings = (\n  diffs: Array<Diff>,\n  op: number,\n  hasCommonDiff: boolean,","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/jest-matcher-utils/src/index.ts#L224-L260","documentation":"Thrown by ensureExpectedIsNonNegativeInteger when the expected value fails any of: typeof !== 'number', Number.isSafeInteger is false, or value < 0. This guard backs matchers whose expected argument is a count or an index — notably toHaveBeenCalledTimes and the n in toHaveBeenCalledNth / toHaveBeenNthCalledWith. Note it deliberately rejects bigint (the check is typeof === 'number' only), negative numbers, NaN, and non-safe integers.","triggerScenarios":"expect(fn).toHaveBeenCalledTimes(-1); expect(fn).toHaveBeenCalledTimes(2.5); expect(fn).toHaveBeenCalledTimes('3'); expect(fn).toHaveBeenCalledTimes(NaN); expect(fn).toHaveBeenCalledTimes(2n); expect(fn).toHaveBeenNthCalledWith(0, ...) (zero-based thinking — n must be >=1).","commonSituations":"Off-by-one confusion between array length and call index; computing the expected count from a float division (arr.length / 2 when length is odd); a dynamically computed count that yields NaN because of an undefined input; assuming bigint works like number for counts.","solutions":["Use a non-negative integer literal or compute one with Math.floor/Math.trunc: expect(fn).toHaveBeenCalledTimes(Math.floor(total / step)).","Verify the count expression with a log before the assertion; fix NaN/undefined sources upstream.","Remember indices are 1-based for nth matchers — pass 1 for the first call, not 0.","Do not pass a bigint count; convert with Number() if a bigint source is involved and it fits in a safe integer."],"exampleFix":"// before\nexpect(handler).toHaveBeenCalledTimes(events.length / 2); // 2.5 when length is 5\n// after\nexpect(handler).toHaveBeenCalledTimes(Math.floor(events.length / 2));","handlingStrategy":"validation","validationCode":"function assertCount(n: unknown): asserts n is number {\n  if (typeof n !== 'number' || !Number.isSafeInteger(n) || n < 0) {\n    throw new Error(`expected call count must be a non-negative integer, got ${n}`);\n  }\n}\nconst expected = Math.floor(events.length / 2);\nassertCount(expected);\nexpect(fn).toHaveBeenCalledTimes(expected);","typeGuard":"const isNonNegInt = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isSafeInteger(v) && v >= 0;\n\nconst expected = isNonNegInt(raw) ? raw : Math.max(0, Math.floor(Number(raw) || 0));\nexpect(fn).toHaveBeenCalledTimes(expected);","tryCatchPattern":null,"preventionTips":["Use Math.floor/Math.trunc on any computed count.","Remember nth-style matchers are 1-indexed.","Never pass a bigint as a call count."],"tags":["matchers","type-error","numeric","jest-matcher-utils","call-count"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}