jestjs/jest · error · Error

Cannot use spyOn on a primitive value; ${this._typeOf(object

Error message

Cannot use spyOn on a primitive value; ${this._typeOf(object)} given

What it means

Thrown by jest.spyOn when the first argument is null, undefined, or a JS primitive (number/string/boolean/symbol). spyOn can only attach a spy to an object or function, so the guard rejects non-object targets up front.

Source

Thrown at packages/jest-mock/src/index.ts:1280

  spyOn<
    T extends object,
    K extends ConstructorLikeKeys<T> | MethodLikeKeys<T>,
    V extends Required<T>[K],
  >(
    object: T,
    methodKey: K,
  ): V extends ClassLike | FunctionLike ? Spied<V> : never;

  spyOn<T extends object>(
    object: T,
    methodKey: keyof T,
    accessType?: 'get' | 'set',
  ): MockInstance {
    if (
      object == null ||
      (typeof object !== 'object' && typeof object !== 'function')
    ) {
      throw new Error(
        `Cannot use spyOn on a primitive value; ${this._typeOf(object)} given`,
      );
    }

    if (methodKey == null) {
      throw new Error('No property name supplied');
    }

    if (accessType) {
      return this._spyOnProperty(object, methodKey, accessType);
    }

    const original = object[methodKey];

    if (!original) {
      throw new Error(
        `Property \`${String(
          methodKey,

View on GitHub (pinned to 8e6d128e4a)

Solutions

  1. Log the first argument to confirm it is an object/function at runtime.
  2. Fix the import (named vs default, correct relative path, check the module's exports field).
  3. Spy on the object that owns the method (e.g. the module namespace object) rather than a primitive it exports.

Example fix

// before
jest.spyOn(logger, 'info');  // logger is undefined because of wrong import
// after
import * as logger from './logger';
jest.spyOn(logger, 'info');
Defensive patterns

Strategy: type-guard

Validate before calling

if (target == null || (typeof target !== 'object' && typeof target !== 'function')) {
  throw new TypeError(`spyOn target must be an object/function, got ${typeof target}`);
}
jest.spyOn(target, methodName);

Type guard

const isSpyable = (x: unknown): x is object =>
  x != null && (typeof x === 'object' || typeof x === 'function');

Prevention

When it happens

Trigger: jest.spyOn(null,'foo'); jest.spyOn(undefined,'bar'); jest.spyOn('hello','length'); jest.spyOn(42,'toString'); jest.spyOn(true,'valueOf').

Common situations: The module/object import resolved to undefined (wrong path, named/default mismatch, ESM vs CJS interop); spying on a re-export that lost the object; tree-shaking removed the binding; passing a destructured primitive instead of the holder object.

Related errors


AI-assisted analysis of jestjs/jest@8e6d128e4a (2026-08-10). Data as JSON: /api/errors/3c0642d4c11567be. Report an issue: GitHub.