You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
assert.deepStrictEqual / util.isDeepStrictEqual throw TypeError on Maps with null keys #64433
The same input crashes assert.deepStrictEqual and assert.notDeepStrictEqual
with the same TypeError (instead of an AssertionError / clean pass).
The triggering shape: one Map has a null key whose value is an object, the
other Map lacks a null key but contains an object key with a deeply-equal
value, plus at least one additional entry. Simpler null-key cases (primitive
values, or no other entries) return correctly, so the crash is in the
second-pass unordered key matching.
How often does it reproduce? Is there a required condition?
Deterministic.
What is the expected behavior? Why is that the expected behavior?
isDeepStrictEqual returns false; assert.deepStrictEqual throws AssertionError; assert.notDeepStrictEqual passes. A comparison predicate
should never throw a TypeError on valid inputs.
What do you see instead?
TypeError: Cannot read properties of null (reading 'constructor')
Additional information
Likely cause: in the fallback pass that pairs non-identical Map keys by deep
equality, keys with typeof key === 'object' are collected for pairwise
comparison, and null (also typeof 'object') reaches a code path that reads key.constructor without a null guard.
Found by differential fuzzing of deep-equality implementations; happy to
provide more failing inputs (they all share the shape above).
I can reproduce this on v24.13.1, and it goes back further than noted: it also repros on v22.17.1, so it looks long-standing rather than a recent regression.
The cause looks like mapObjectEquiv in lib/internal/util/comparisons.js. It only special-cases a null or primitive key from the first map when extraChecks is true, where extraChecks = mode === kLoose || array.length !== a.size. In this repro both maps have the same size and b's two object keys fill array, so array.length === a.size and extraChecks is false. That means the null key skips the typeof key1 !== 'object' || key1 === null guard and falls straight into comparator(key1, key2), which for strict mode is objectComparisonStart. That function reads val1.constructor with no null check, and since typeof null is 'object' the null isn't filtered out earlier, which is where the "Cannot read properties of null" comes from.
So I think the fix is just guarding null before that comparator call. Happy to put up a PR. This looks like a confirmed-bug in assert/util.
Activity
hunt: differential harness + round-2 findings — node core crash found…
bitpshr commentedon Jul 12, 2026
I can reproduce this on v24.13.1, and it goes back further than noted: it also repros on v22.17.1, so it looks long-standing rather than a recent regression.
The cause looks like
mapObjectEquivinlib/internal/util/comparisons.js. It only special-cases anullor primitive key from the first map whenextraChecksis true, whereextraChecks = mode === kLoose || array.length !== a.size. In this repro both maps have the same size andb's two object keys fillarray, soarray.length === a.sizeandextraChecksis false. That means thenullkey skips thetypeof key1 !== 'object' || key1 === nullguard and falls straight intocomparator(key1, key2), which for strict mode isobjectComparisonStart. That function readsval1.constructorwith no null check, and sincetypeof nullis'object'the null isn't filtered out earlier, which is where the "Cannot read properties of null" comes from.So I think the fix is just guarding
nullbefore that comparator call. Happy to put up a PR. This looks like aconfirmed-buginassert/util.assert,util: fix TypeError on Maps with null keys
assert,util: fix TypeError on Maps with null keys
assert,util: fix TypeError on Maps with null keys
assert,util: fix TypeError on Maps with null keys
assert,util: fix TypeError on Maps with null keys
assert,util: fix TypeError on Maps with null keys
docs: freshness — README test count matched to the actual suite (~75,…