denoland/deno · error · ERR_INVALID_ARG_TYPE
ERR_INVALID_ARG_TYPE
ERR_INVALID_ARG_TYPE
Error message
The "options.serializers" property must be an instance of Array. Received ${actual} What it means
In node:test snapshot testing, t.assert.fileSnapshot(value, path, options) validates its options: if options.serializers is supplied it must be an Array (fileSnapshot assigns it element-by-element to run each serializer over the value). Passing anything else — most often a bare serializer function — throws ERR_INVALID_ARG_TYPE naming 'options.serializers' with expected type 'Array'. When omitted, the default file snapshot serializer is used.
Source
Thrown at ext/node/polyfills/testing.ts:342
// `t.assert.fileSnapshot(value, path[, options])`.
//
// Without `--test-update-snapshots`, serializes `value` and compares against
// the contents of the file at `path` using `assert.strictEqual`. With the
// flag, writes the serialized value to `path` (creating parent directories
// as needed). Both file paths are CWD-relative, matching Node.
function fileSnapshot(actual, path, options) {
validateString(path, "path");
if (options === undefined) {
options = { __proto__: null };
} else {
validateObject(options, "options");
}
let serializers;
if (options.serializers === undefined) {
serializers = [defaultFileSnapshotSerializer];
} else {
if (!ArrayIsArray(options.serializers)) {
throw new ERR_INVALID_ARG_TYPE(
"options.serializers",
"Array",
options.serializers,
);
}
serializers = options.serializers;
for (let i = 0; i < serializers.length; i++) {
if (typeof serializers[i] !== "function") {
throw new ERR_INVALID_ARG_TYPE(
`options.serializers[${i}]`,
"function",
serializers[i],
);
}
}
}
let value = actual;
try {View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Wrap the serializer in an array: { serializers: [mySerializer] }
- Omit the serializers option entirely to use the default file snapshot serializer
- Order matters: serializers run left-to-right, each receiving the previous one's output — keep the array order intentional
Example fix
// before
t.assert.fileSnapshot(body, 'snap.txt', { serializers: mySerializer });
// after
t.assert.fileSnapshot(body, 'snap.txt', { serializers: [mySerializer] }); Defensive patterns
Strategy: validation
Validate before calling
function normalizeSerializers(options) {
const serializers = options?.serializers;
if (serializers === undefined) return undefined;
if (!Array.isArray(serializers)) {
throw new TypeError('options.serializers must be an Array');
}
return serializers;
}
const serializers = normalizeSerializers(opts);
t.assert.fileSnapshot(body, 'snap.txt', { serializers }); Type guard
const isSerializerArray = (v) => v === undefined || (Array.isArray(v) && v.every((s) => typeof s === 'function'));
Prevention
- Always write serializers as an array literal: { serializers: [stripDates] }
- Omit the option to use the default snapshot serializer
- Centralize serializer lists in one typed constant so every fileSnapshot call shares a validated shape
When it happens
Trigger: t.assert.fileSnapshot(body, 'snap.txt', { serializers: mySerializer }) with a bare function instead of an array; passing a string, object, or null as serializers.
Common situations: Developers coming from APIs that accept a single function; copy-pasting a serializer from another test library; refactoring that drops the array brackets around an existing list.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- ERR_INVALID_ARG_VALUE
- Limit must be a positive integer: received ${options.limit}
- batchSize must be a positive integer: received ${batchSize}
- Invalid port (expected number): ${maybePort}
- ERR_MISSING_ARGS
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/91baaebd1d695f71.
Report an issue: GitHub.