jestjs/jest · error · TypeError
Primitives cannot leak memory. You passed a ${typeof value}:
Error message
Primitives cannot leak memory. You passed a ${typeof value}: <${prettyFormat(value)}> What it means
Thrown by the `LeakDetector` constructor in jest-leak-detector/index.ts:28 when the value passed is a primitive (`isPrimitive(value)` true). Leak detection relies on a `FinalizationRegistry` weakly tracking an object; primitives are passed by value and cannot hold a strong reference, so tracking them is meaningless and the constructor rejects them with a TypeError.
Source
Thrown at packages/jest-leak-detector/src/index.ts:28
import {getHeapSnapshot, setFlagsFromString} from 'node:v8';
import {runInNewContext} from 'node:vm';
import {isPrimitive} from '@jest/get-type';
import {format as prettyFormat} from 'pretty-format';
interface LeakDetectorOptions {
shouldGenerateV8HeapSnapshot: boolean;
}
const tick = promisify(setImmediate);
export default class LeakDetector {
private _isReferenceBeingHeld: boolean;
private _shouldGenerateV8HeapSnapshot: boolean;
private readonly _finalizationRegistry?: FinalizationRegistry<undefined>;
constructor(value: unknown, opt?: LeakDetectorOptions) {
if (isPrimitive(value)) {
throw new TypeError(
[
'Primitives cannot leak memory.',
`You passed a ${typeof value}: <${prettyFormat(value)}>`,
].join(' '),
);
}
// When `_finalizationRegistry` is GCed the callback we set will no longer be called,
this._finalizationRegistry = new FinalizationRegistry(() => {
this._isReferenceBeingHeld = false;
});
this._finalizationRegistry.register(value as object, undefined);
this._isReferenceBeingHeld = true;
this._shouldGenerateV8HeapSnapshot =
opt?.shouldGenerateV8HeapSnapshot ?? true;
View on GitHub (pinned to f49721c78e)
Solutions
- Pass an object/function/array instead of a primitive.
- If the value is logically a primitive, skip leak detection for that test (it cannot leak by definition).
- Wrap the primitive in an object only if you genuinely need to detect references to the wrapper.
Example fix
// before
new LeakDetector('config-value')
// after
new LeakDetector({ value: 'config-value' }) Defensive patterns
Strategy: type-guard
Validate before calling
import {isPrimitive} from '@jest/get-type';
if (isPrimitive(value)) { /* skip detection, primitives can't leak */ return; }
new LeakDetector(value); Type guard
const isTrackable = (v: unknown): v is object => v != null && (typeof v === 'object' || typeof v === 'function');
Prevention
- Only construct LeakDetector with objects, functions, or arrays.
- In --detectLeaks test setups, ensure the module under test exports an object.
When it happens
Trigger: Constructing `new LeakDetector('foo')`, `new LeakDetector(42)`, `new LeakDetector(true)`, `new LeakDetector(null)`, `new LeakDetector(Symbol())`, or `new LeakDetector(0n)`. Most commonly hit indirectly when a test that uses `--detectLeaks` exports or returns a primitive as the module under test.
Common situations: Running Jest with `--detectOpenHandles`/`--detectLeaks` against a test module whose default export is a primitive (string/number); a leak-detector unit test that feeds a literal; wrapping a JSON config value.
AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03).
Data as JSON: /data/errors/3b4ea898a8b6a941.json.
Report an issue: GitHub.