jestjs/jest · error · Error

expected value must be a non-negative integer

Error message

expected value must be a non-negative integer

What it means

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.

Source

Thrown at packages/jest-matcher-utils/src/index.ts:242

  options?: MatcherHintOptions,
): void => {
  ensureActualIsNumber(actual, matcherName, options);
  ensureExpectedIsNumber(expected, matcherName, options);
};

export const ensureExpectedIsNonNegativeInteger = (
  expected: unknown,
  matcherName: string,
  options?: MatcherHintOptions,
): void => {
  if (
    typeof expected !== 'number' ||
    !Number.isSafeInteger(expected) ||
    expected < 0
  ) {
    // Prepend maybe not only for backward compatibility.
    const matcherString = (options ? '' : '[.not]') + matcherName;
    throw new Error(
      matcherErrorMessage(
        matcherHint(matcherString, undefined, undefined, options),
        `${EXPECTED_COLOR('expected')} value must be a non-negative integer`,
        printWithType('Expected', expected, printExpected),
      ),
    );
  }
};

// Given array of diffs, return concatenated string:
// * include common substrings
// * exclude change substrings which have opposite op
// * include change substrings which have argument op
//   with inverse highlight only if there is a common substring
const getCommonAndChangedSubstrings = (
  diffs: Array<Diff>,
  op: number,
  hasCommonDiff: boolean,

View on GitHub (pinned to f49721c78e)

Solutions

  1. Use a non-negative integer literal or compute one with Math.floor/Math.trunc: expect(fn).toHaveBeenCalledTimes(Math.floor(total / step)).
  2. Verify the count expression with a log before the assertion; fix NaN/undefined sources upstream.
  3. Remember indices are 1-based for nth matchers — pass 1 for the first call, not 0.
  4. Do not pass a bigint count; convert with Number() if a bigint source is involved and it fits in a safe integer.

Example fix

// before
expect(handler).toHaveBeenCalledTimes(events.length / 2); // 2.5 when length is 5
// after
expect(handler).toHaveBeenCalledTimes(Math.floor(events.length / 2));
Defensive patterns

Strategy: validation

Validate before calling

function assertCount(n: unknown): asserts n is number {
  if (typeof n !== 'number' || !Number.isSafeInteger(n) || n < 0) {
    throw new Error(`expected call count must be a non-negative integer, got ${n}`);
  }
}
const expected = Math.floor(events.length / 2);
assertCount(expected);
expect(fn).toHaveBeenCalledTimes(expected);

Type guard

const isNonNegInt = (v: unknown): v is number =>
  typeof v === 'number' && Number.isSafeInteger(v) && v >= 0;

const expected = isNonNegInt(raw) ? raw : Math.max(0, Math.floor(Number(raw) || 0));
expect(fn).toHaveBeenCalledTimes(expected);

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03). Data as JSON: /data/errors/b9ba1fc8fe4178a0.json. Report an issue: GitHub.