jestjs/jest · error · Error

expected path must be a string or array

Error message

expected path must be a string or array

What it means

Thrown by `toHaveProperty` (matchers.ts:711) when the first argument (the key path) is neither a string nor an array. `toHaveProperty` accepts a dot/bracket string (`'a.b[0].c'`) or an array of keys (`['a', 'b', '0', 'c']`); any other type (number, object, null) cannot be traversed. The check uses `getType(expectedPath)` and rejects anything whose type isn't `'string'` or `'array'`.

Source

Thrown at packages/expect/src/matchers.ts:738

      isNot: this.isNot,
      promise: this.promise,
      secondArgument: hasValue ? 'value' : '',
    };

    if (received === null || received === undefined) {
      throw new Error(
        matcherErrorMessage(
          matcherHint(matcherName, undefined, expectedArgument, options),
          `${RECEIVED_COLOR('received')} value must not be null nor undefined`,
          printWithType('Received', received, printReceived),
        ),
      );
    }

    const expectedPathType = getType(expectedPath);

    if (expectedPathType !== 'string' && expectedPathType !== 'array') {
      throw new Error(
        matcherErrorMessage(
          matcherHint(matcherName, undefined, expectedArgument, options),
          `${EXPECTED_COLOR('expected')} path must be a string or array`,
          printWithType('Expected', expectedPath, printExpected),
        ),
      );
    }

    const expectedPathLength =
      typeof expectedPath === 'string'
        ? pathAsArray(expectedPath).length
        : expectedPath.length;

    if (expectedPathType === 'array' && expectedPathLength === 0) {
      throw new Error(
        matcherErrorMessage(
          matcherHint(matcherName, undefined, expectedArgument, options),
          `${EXPECTED_COLOR('expected')} path must not be an empty array`,

View on GitHub (pinned to f49721c78e)

Solutions

  1. Convert the path to a string: `.toHaveProperty(String(key))`.
  2. Use the array form for clarity: `.toHaveProperty([String(key)])`.
  3. Log `typeof expectedPath` and `Array.isArray(expectedPath)` to confirm shape.
  4. If the path comes from a dynamic source, validate it before the test.

Example fix

// before
expect(arr).toHaveProperty(index); // index is a number

// after
expect(arr).toHaveProperty(String(index));
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof path !== 'string' && !Array.isArray(path)) {
  throw new Error(`path must be string or array, got ${typeof path}`);
}
expect(obj).toHaveProperty(path);

Type guard

const isPath = (v: unknown): v is string | Array<unknown> =>
  typeof v === 'string' || Array.isArray(v);

Try / catch

try {
  expect(obj).toHaveProperty(path);
} catch (e) {
  if (e instanceof Error && /path must be a string or array/.test(e.message)) {
    console.error('path was', typeof path, path);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `expect(obj).toHaveProperty(42)` (number), `.toHaveProperty({key: 'a'})` (object), `.toHaveProperty(null)`, `.toHaveProperty(true)`, or passing a Symbol. Note: a single-key string is valid, but a raw number like an array index is not — it must be `'42'` or `['42']`.

Common situations: Passing a computed numeric key directly instead of wrapping as string; passing a path object from a helper library; refactor that changed a path variable from string to number; copy-paste from a different matcher API.

Related errors


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