assert.strict
Exposes the assert module in strict assertion mode, where loose methods compare like their strict twins.
assert.strict- Added in Node.js v9.9.0
Return value
ObjectThe assert module bound to strict assertion mode. It is itself callable (equivalent to assert.ok()) and carries every assert method, plus a self-referencing strict property.
Errors
Nothing on access; the methods reached through it throw AssertionError with code ERR_ASSERTION when a check fails.
Changelog
- PHP v15.0.0Strict assertion mode is also exposed as its own module, require('node:assert/strict').
- PHP v13.9.0, v12.16.2Renamed "strict mode" to "strict assertion mode" and "legacy mode" to "legacy assertion mode" to avoid confusion with JavaScript's own strict mode.
- PHP v9.9.0Strict assertion mode added, along with error diffs in its failure messages.
assert.strict is not a check of its own. It is the whole assert module handed back with one rule changed: the four loose methods stop using ==. equal() becomes strictEqual(), deepEqual() becomes deepStrictEqual(), and likewise for the two negated forms. Everything else — ok(), throws(), rejects(), match() — is the same function object you would get from plain node:assert.
Reach for it
At the top of every test file, so nobody on the team has to remember which method name is the safe one. Three spellings give you the same object:
const assert = require('node:assert/strict');
const assert = require('node:assert').strict;
import { strict as assert } from 'node:assert';What trips people up
Legacy mode is quiet in exactly the cases you most want to catch. assert.deepEqual({ n: 1 }, { n: '1' }) passes, and the docs' own example, assert.deepEqual(/a/gi, new Date()), passes too. Under strict mode both throw.
The second payoff is the failure output. Strict mode prints a line-by-line diff of the two objects; legacy mode dumps both values, usually truncated, and leaves you to spot the difference by eye.
Example
When to use it
- Standardising a test suite so equal() and deepEqual() can never silently pass on a type mismatch
- Getting a readable diff instead of two truncated object dumps when a deep comparison fails
- Migrating older tests off deepEqual() without rewriting every call site by hand
- Writing node:test files where the assertion style should match the strict default
Frequently asked questions
What is the difference between node:assert and node:assert/strict?
They expose the same methods; node:assert/strict only changes what equal(), notEqual(), deepEqual() and notDeepEqual() do, making them behave as strictEqual(), notStrictEqual(), deepStrictEqual() and notDeepStrictEqual(). Every other method — ok(), throws(), rejects(), match(), fail() — is literally the same function in both. Strict mode also prints a diff on object failures instead of dumping both values.
Why does assert.deepEqual pass when the objects are clearly different?
Because plain assert.deepEqual() compares with ==, so 1 matches '1' and, in the documented extreme, /a/gi matches new Date(). Switching the import to node:assert/strict makes the same call compare with Object.is and SameValueZero semantics, and it will then throw. This is the single most common reason people reach for strict assertion mode.
Is assert.strict deprecated in Node.js?
No — assert.strict is the recommended mode and is not deprecated. It is the loose methods it replaces that carry a reduced stability rating: assert.deepEqual() and friends are marked Stability 3 (Legacy), downgraded from Deprecated in v16.0.0 and v14.18.0. Strict assertion mode has been available since v9.9.0 and gained its own module path in v15.0.0.
More examples
The error diff strict mode gives you
The message points at the one element that differs — 3 against '3' — and elides the matching lines. The same failure in legacy mode prints both arrays in full and says only that they are not deeply equal, so you compare them yourself. Set NO_COLOR or NODE_DISABLE_COLORS to strip the ANSI colours from this output, for example when capturing it into a log file.
import { strict as assert } from 'node:assert';
try {
assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]);
} catch (err) {
console.log(err.message);
}
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected ... Lines skipped
//
// [
// [
// ...
// 2,
// + 3
// - '3'
// ],
// ...
// 5
// ]One import for a node:test file
Importing the strict module as `assert` means the short method names are the safe ones throughout the file — a reviewer never has to check whether a call site used equal() or strictEqual(). The second test shows the module object is itself a function equivalent to assert.ok(), so `assert(value)` works. Had parseRange forgotten its Number() calls, the first test would fail on a string-versus-number mismatch that legacy deepEqual() would have let through.
import test from 'node:test';
import assert from 'node:assert/strict';
function parseRange(input) {
const [from, to] = input.split('-');
return { from: Number(from), to: Number(to) };
}
test('parseRange returns numbers, not strings', () => {
// deepEqual here is deepStrictEqual, so { from: '1' } would fail.
assert.deepEqual(parseRange('1-10'), { from: 1, to: 10 });
});
test('assert.strict is callable, like assert.ok', () => {
assert(parseRange('2-3').to > parseRange('2-3').from);
});
test('strict methods are still reachable by their long names', () => {
assert.strictEqual(parseRange('4-4').from, 4);
});Turning a legacy file strict, one require at a time
Both assertions passed under legacy mode purely because of coercion — a port read from an environment variable stays a string, and 0 == false. Swapping the require line, with no change to any call site, surfaces both bugs as ERR_ASSERTION failures whose operator field reports strictEqual rather than equal. That operator name is the quickest way to confirm at runtime that a file really is running in strict assertion mode.
// Before: loose comparisons hidden behind short names.
const assert = require('node:assert');
const config = { port: '8080', debug: 0 };
assert.equal(config.port, 8080); // passes: '8080' == 8080
assert.equal(config.debug, false); // passes: 0 == false
console.log('legacy: both assertions passed');
// After: same call sites, strict module.
const strictAssert = require('node:assert').strict;
for (const [label, actual, expected] of [
['port', config.port, 8080],
['debug', config.debug, false],
]) {
try {
strictAssert.equal(actual, expected);
console.log(`strict ${label}: passed`);
} catch (err) {
console.log(`strict ${label}: ${err.code} (${err.operator})`);
}
}
// legacy: both assertions passed
// strict port: ERR_ASSERTION (strictEqual)
// strict debug: ERR_ASSERTION (strictEqual)
Discussion