diff --git a/doc/api/errors.md b/doc/api/errors.md
index 3d2761b54cb7b0..39053ab3d357dd 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -1136,6 +1136,11 @@ Used when an attempt is made to launch a Node.js process with an unknown
by errors in user code, although it is not impossible. Occurrences of this error
are most likely an indication of a bug within Node.js itself.
+
+### ERR_VALUE_OUT_OF_RANGE
+
+Used when a number value is out of range.
+
### ERR_V8BREAKITERATOR
diff --git a/lib/fs.js b/lib/fs.js
index 7c4e68358b33c2..04db546c769cf1 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -33,6 +33,7 @@ const { isUint8Array, createPromise, promiseResolve } = process.binding('util');
const binding = process.binding('fs');
const fs = exports;
const Buffer = require('buffer').Buffer;
+const errors = require('internal/errors');
const Stream = require('stream').Stream;
const EventEmitter = require('events');
const FSReqWrap = binding.FSReqWrap;
@@ -72,8 +73,10 @@ function getOptions(options, defaultOptions) {
defaultOptions.encoding = options;
options = defaultOptions;
} else if (typeof options !== 'object') {
- throw new TypeError('"options" must be a string or an object, got ' +
- typeof options + ' instead.');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
+ 'options',
+ ['string', 'object'],
+ options);
}
if (options.encoding !== 'buffer')
@@ -128,7 +131,7 @@ function makeCallback(cb) {
}
if (typeof cb !== 'function') {
- throw new TypeError('"callback" argument must be a function');
+ throw new errors.TypeError('ERR_INVALID_CALLBACK');
}
return function() {
@@ -145,7 +148,7 @@ function makeStatsCallback(cb) {
}
if (typeof cb !== 'function') {
- throw new TypeError('"callback" argument must be a function');
+ throw new errors.TypeError('ERR_INVALID_CALLBACK');
}
return function(err) {
@@ -156,8 +159,11 @@ function makeStatsCallback(cb) {
function nullCheck(path, callback) {
if (('' + path).indexOf('\u0000') !== -1) {
- var er = new Error('Path must be a string without null bytes');
- er.code = 'ENOENT';
+ const er = new errors.Error('ERR_INVALID_ARG_TYPE',
+ 'path',
+ 'string without null bytes',
+ path);
+
if (typeof callback !== 'function')
throw er;
process.nextTick(callback, er);
@@ -274,7 +280,7 @@ fs.access = function(path, mode, callback) {
callback = mode;
mode = fs.F_OK;
} else if (typeof callback !== 'function') {
- throw new TypeError('"callback" argument must be a function');
+ throw new errors.TypeError('ERR_INVALID_CALLBACK');
}
if (handleError((path = getPathFromURL(path)), callback))
@@ -1193,7 +1199,10 @@ function toUnixTimestamp(time) {
// convert to 123.456 UNIX timestamp
return time.getTime() / 1000;
}
- throw new Error('Cannot parse time: ' + time);
+ throw new errors.Error('ERR_INVALID_ARG_TYPE',
+ 'time',
+ ['Date', 'time in seconds'],
+ time);
}
// exported for unit tests, not for public consumption
@@ -1495,7 +1504,10 @@ fs.watchFile = function(filename, options, listener) {
}
if (typeof listener !== 'function') {
- throw new Error('"watchFile()" requires a listener function');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
+ 'listener',
+ 'function',
+ listener);
}
stat = statWatchers.get(filename);
@@ -1842,8 +1854,12 @@ fs.realpath = function realpath(p, options, callback) {
fs.mkdtemp = function(prefix, options, callback) {
callback = makeCallback(typeof options === 'function' ? options : callback);
options = getOptions(options, {});
- if (!prefix || typeof prefix !== 'string')
- throw new TypeError('filename prefix is required');
+ if (!prefix || typeof prefix !== 'string') {
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
+ 'prefix',
+ 'string',
+ prefix);
+ }
if (!nullCheck(prefix, callback)) {
return;
}
@@ -1856,8 +1872,12 @@ fs.mkdtemp = function(prefix, options, callback) {
fs.mkdtempSync = function(prefix, options) {
- if (!prefix || typeof prefix !== 'string')
- throw new TypeError('filename prefix is required');
+ if (!prefix || typeof prefix !== 'string') {
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
+ 'prefix',
+ 'string',
+ prefix);
+ }
options = getOptions(options, {});
nullCheck(prefix);
return binding.mkdtemp(prefix + 'XXXXXX', options.encoding);
@@ -1903,16 +1923,26 @@ function ReadStream(path, options) {
if (this.start !== undefined) {
if (typeof this.start !== 'number') {
- throw new TypeError('"start" option must be a Number');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
+ 'start',
+ 'number',
+ this.start);
}
if (this.end === undefined) {
this.end = Infinity;
} else if (typeof this.end !== 'number') {
- throw new TypeError('"end" option must be a Number');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
+ 'end',
+ 'number',
+ this.end);
}
if (this.start > this.end) {
- throw new Error('"start" option must be <= "end" option');
+ const errVal = `{start: ${this.start}, end: ${this.end}}`;
+ throw new errors.RangeError('ERR_VALUE_OUT_OF_RANGE',
+ 'start',
+ '<= "end"',
+ errVal);
}
this.pos = this.start;
@@ -2069,10 +2099,17 @@ function WriteStream(path, options) {
if (this.start !== undefined) {
if (typeof this.start !== 'number') {
- throw new TypeError('"start" option must be a Number');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
+ 'start',
+ 'number',
+ this.start);
}
if (this.start < 0) {
- throw new Error('"start" must be >= zero');
+ const errVal = `{start: ${this.start}}`;
+ throw new errors.RangeError('ERR_VALUE_OUT_OF_RANGE',
+ 'start',
+ '>= 0',
+ errVal);
}
this.pos = this.start;
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index c90cd82e305d3c..9ed28119b10701 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -264,6 +264,9 @@ E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s');
E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s');
E('ERR_UNKNOWN_STDIN_TYPE', 'Unknown stdin file type');
E('ERR_UNKNOWN_STREAM_TYPE', 'Unknown stream file type');
+E('ERR_VALUE_OUT_OF_RANGE', (start, end, value) => {
+ return `The value of "${start}" must be ${end}. Received "${value}"`;
+});
E('ERR_V8BREAKITERATOR', 'Full ICU data not installed. ' +
'See https://github.com/nodejs/node/wiki/Intl');
E('ERR_VALID_PERFORMANCE_ENTRY_TYPE',
diff --git a/test/parallel/test-file-write-stream3.js b/test/parallel/test-file-write-stream3.js
index 83b1d7bf439a07..cdc01e873389a2 100644
--- a/test/parallel/test-file-write-stream3.js
+++ b/test/parallel/test-file-write-stream3.js
@@ -176,12 +176,15 @@ function run_test_3() {
const run_test_4 = common.mustCall(function() {
// Error: start must be >= zero
- assert.throws(
- function() {
- fs.createWriteStream(filepath, { start: -5, flags: 'r+' });
- },
- /"start" must be/
- );
+ const block = () => {
+ fs.createWriteStream(filepath, { start: -5, flags: 'r+' });
+ };
+ const err = {
+ code: 'ERR_VALUE_OUT_OF_RANGE',
+ message: 'The value of "start" must be >= 0. Received "{start: -5}"',
+ type: RangeError
+ };
+ common.expectsError(block, err);
});
run_test_1();
diff --git a/test/parallel/test-fs-access.js b/test/parallel/test-fs-access.js
index f378824cbcd950..d3140941bd0e72 100644
--- a/test/parallel/test-fs-access.js
+++ b/test/parallel/test-fs-access.js
@@ -85,13 +85,23 @@ assert.throws(() => {
fs.access(100, fs.F_OK, common.mustNotCall());
}, /^TypeError: path must be a string or Buffer$/);
-assert.throws(() => {
- fs.access(__filename, fs.F_OK);
-}, /^TypeError: "callback" argument must be a function$/);
-
-assert.throws(() => {
- fs.access(__filename, fs.F_OK, {});
-}, /^TypeError: "callback" argument must be a function$/);
+common.expectsError(
+ () => {
+ fs.access(__filename, fs.F_OK);
+ },
+ {
+ code: 'ERR_INVALID_CALLBACK',
+ type: TypeError
+ });
+
+common.expectsError(
+ () => {
+ fs.access(__filename, fs.F_OK, {});
+ },
+ {
+ code: 'ERR_INVALID_CALLBACK',
+ type: TypeError
+ });
assert.doesNotThrow(() => {
fs.accessSync(__filename);
diff --git a/test/parallel/test-fs-make-callback.js b/test/parallel/test-fs-make-callback.js
index 8a19e1cc9601f4..79cf4e0bed7525 100644
--- a/test/parallel/test-fs-make-callback.js
+++ b/test/parallel/test-fs-make-callback.js
@@ -2,7 +2,6 @@
const common = require('../common');
const assert = require('assert');
const fs = require('fs');
-const cbTypeError = /^TypeError: "callback" argument must be a function$/;
const callbackThrowValues = [null, true, false, 0, 1, 'foo', /foo/, [], {}];
const { sep } = require('path');
@@ -24,7 +23,10 @@ assert.doesNotThrow(testMakeCallback());
function invalidCallbackThrowsTests() {
callbackThrowValues.forEach((value) => {
- assert.throws(testMakeCallback(value), cbTypeError);
+ common.expectsError(testMakeCallback(value), {
+ code: 'ERR_INVALID_CALLBACK',
+ type: TypeError
+ });
});
}
diff --git a/test/parallel/test-fs-makeStatsCallback.js b/test/parallel/test-fs-makeStatsCallback.js
index 12120e97376424..0982fcc3c7d38c 100644
--- a/test/parallel/test-fs-makeStatsCallback.js
+++ b/test/parallel/test-fs-makeStatsCallback.js
@@ -2,7 +2,6 @@
const common = require('../common');
const assert = require('assert');
const fs = require('fs');
-const cbTypeError = /^TypeError: "callback" argument must be a function$/;
const callbackThrowValues = [null, true, false, 0, 1, 'foo', /foo/, [], {}];
const warn = 'Calling an asynchronous function without callback is deprecated.';
@@ -23,7 +22,10 @@ assert.doesNotThrow(testMakeStatsCallback());
function invalidCallbackThrowsTests() {
callbackThrowValues.forEach((value) => {
- assert.throws(testMakeStatsCallback(value), cbTypeError);
+ common.expectsError(testMakeStatsCallback(value), {
+ code: 'ERR_INVALID_CALLBACK',
+ type: TypeError
+ });
});
}
diff --git a/test/parallel/test-fs-mkdtemp-prefix-check.js b/test/parallel/test-fs-mkdtemp-prefix-check.js
index 786d0fe7bae169..4573dbbaae8435 100644
--- a/test/parallel/test-fs-mkdtemp-prefix-check.js
+++ b/test/parallel/test-fs-mkdtemp-prefix-check.js
@@ -1,22 +1,29 @@
'use strict';
const common = require('../common');
-const assert = require('assert');
const fs = require('fs');
-const expectedError = /^TypeError: filename prefix is required$/;
const prefixValues = [undefined, null, 0, true, false, 1, ''];
function fail(value) {
- assert.throws(
- () => fs.mkdtempSync(value, {}),
- expectedError
- );
+ common.expectsError(
+ () => {
+ fs.mkdtempSync(value, {});
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError
+ });
}
function failAsync(value) {
- assert.throws(
- () => fs.mkdtemp(value, common.mustNotCall()), expectedError
- );
+ common.expectsError(
+ () => {
+ fs.mkdtemp(value, common.mustNotCall());
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError
+ });
}
prefixValues.forEach((prefixValue) => {
diff --git a/test/parallel/test-fs-non-number-arguments-throw.js b/test/parallel/test-fs-non-number-arguments-throw.js
index 5e4deb12a8734b..9e73502c2908fa 100644
--- a/test/parallel/test-fs-non-number-arguments-throw.js
+++ b/test/parallel/test-fs-non-number-arguments-throw.js
@@ -13,20 +13,32 @@ fs.writeFileSync(tempFile, 'abc\ndef');
const sanity = 'def';
const saneEmitter = fs.createReadStream(tempFile, { start: 4, end: 6 });
-assert.throws(function() {
- fs.createReadStream(tempFile, { start: '4', end: 6 });
-}, /^TypeError: "start" option must be a Number$/,
- "start as string didn't throw an error for createReadStream");
+common.expectsError(
+ () => {
+ fs.createReadStream(tempFile, { start: '4', end: 6 });
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError
+ });
-assert.throws(function() {
- fs.createReadStream(tempFile, { start: 4, end: '6' });
-}, /^TypeError: "end" option must be a Number$/,
- "end as string didn't throw an error for createReadStream");
+common.expectsError(
+ () => {
+ fs.createReadStream(tempFile, { start: 4, end: '6' });
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError
+ });
-assert.throws(function() {
- fs.createWriteStream(tempFile, { start: '4' });
-}, /^TypeError: "start" option must be a Number$/,
- "start as string didn't throw an error for createWriteStream");
+common.expectsError(
+ () => {
+ fs.createWriteStream(tempFile, { start: '4' });
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError
+ });
saneEmitter.on('data', common.mustCall(function(data) {
assert.strictEqual(
diff --git a/test/parallel/test-fs-null-bytes.js b/test/parallel/test-fs-null-bytes.js
index 0552801b2deaa9..44defc782ee139 100644
--- a/test/parallel/test-fs-null-bytes.js
+++ b/test/parallel/test-fs-null-bytes.js
@@ -26,17 +26,27 @@ const fs = require('fs');
const URL = require('url').URL;
function check(async, sync) {
- const expected = /Path must be a string without null bytes/;
const argsSync = Array.prototype.slice.call(arguments, 2);
const argsAsync = argsSync.concat((er) => {
- assert(er && expected.test(er.message));
- assert.strictEqual(er.code, 'ENOENT');
+ common.expectsError(
+ () => {
+ throw er;
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: Error
+ });
});
if (sync) {
- assert.throws(() => {
- sync.apply(null, argsSync);
- }, expected);
+ common.expectsError(
+ () => {
+ sync.apply(null, argsSync);
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: Error,
+ });
}
if (async) {
diff --git a/test/parallel/test-fs-read-stream-inherit.js b/test/parallel/test-fs-read-stream-inherit.js
index ddb07274d1f887..1a7fc7b5bb75e0 100644
--- a/test/parallel/test-fs-read-stream-inherit.js
+++ b/test/parallel/test-fs-read-stream-inherit.js
@@ -108,9 +108,18 @@ const rangeFile = path.join(common.fixturesDir, 'x.txt');
}
{
- assert.throws(function() {
- fs.createReadStream(rangeFile, Object.create({ start: 10, end: 2 }));
- }, /"start" option must be <= "end" option/);
+ const message =
+ 'The value of "start" must be <= "end". Received "{start: 10, end: 2}"';
+
+ common.expectsError(
+ () => {
+ fs.createReadStream(rangeFile, Object.create({ start: 10, end: 2 }));
+ },
+ {
+ code: 'ERR_VALUE_OUT_OF_RANGE',
+ message,
+ type: RangeError
+ });
}
{
diff --git a/test/parallel/test-fs-read-stream-throw-type-error.js b/test/parallel/test-fs-read-stream-throw-type-error.js
index b6e1869fdc2cc9..61308ea97b8283 100644
--- a/test/parallel/test-fs-read-stream-throw-type-error.js
+++ b/test/parallel/test-fs-read-stream-throw-type-error.js
@@ -19,16 +19,18 @@ assert.doesNotThrow(function() {
fs.createReadStream(example, { encoding: 'utf8' });
});
-const errMessage = /"options" must be a string or an object/;
-assert.throws(function() {
- fs.createReadStream(example, 123);
-}, errMessage);
-assert.throws(function() {
- fs.createReadStream(example, 0);
-}, errMessage);
-assert.throws(function() {
- fs.createReadStream(example, true);
-}, errMessage);
-assert.throws(function() {
- fs.createReadStream(example, false);
-}, errMessage);
+const createReadStreamErr = (path, opt) => {
+ common.expectsError(
+ () => {
+ fs.createReadStream(path, opt);
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError
+ });
+};
+
+createReadStreamErr(example, 123);
+createReadStreamErr(example, 0);
+createReadStreamErr(example, true);
+createReadStreamErr(example, false);
diff --git a/test/parallel/test-fs-read-stream.js b/test/parallel/test-fs-read-stream.js
index 04c10b5a4415c1..ecc00edc851c55 100644
--- a/test/parallel/test-fs-read-stream.js
+++ b/test/parallel/test-fs-read-stream.js
@@ -140,9 +140,16 @@ const rangeFile = fixtures.path('x.txt');
}));
}
-assert.throws(function() {
- fs.createReadStream(rangeFile, { start: 10, end: 2 });
-}, /"start" option must be <= "end" option/);
+common.expectsError(
+ () => {
+ fs.createReadStream(rangeFile, { start: 10, end: 2 });
+ },
+ {
+ code: 'ERR_VALUE_OUT_OF_RANGE',
+ message:
+ 'The value of "start" must be <= "end". Received "{start: 10, end: 2}"',
+ type: RangeError
+ });
{
const stream = fs.createReadStream(rangeFile, { start: 0, end: 0 });
diff --git a/test/parallel/test-fs-timestamp-parsing-error.js b/test/parallel/test-fs-timestamp-parsing-error.js
index c37cf674a4d4d7..3680b5fece13c9 100644
--- a/test/parallel/test-fs-timestamp-parsing-error.js
+++ b/test/parallel/test-fs-timestamp-parsing-error.js
@@ -1,15 +1,27 @@
'use strict';
-require('../common');
+const common = require('../common');
const fs = require('fs');
const assert = require('assert');
[Infinity, -Infinity, NaN].forEach((input) => {
- assert.throws(() => fs._toUnixTimestamp(input),
- new RegExp(`^Error: Cannot parse time: ${input}$`));
+ common.expectsError(
+ () => {
+ fs._toUnixTimestamp(input);
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: Error
+ });
});
-assert.throws(() => fs._toUnixTimestamp({}),
- /^Error: Cannot parse time: \[object Object\]$/);
+common.expectsError(
+ () => {
+ fs._toUnixTimestamp({});
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: Error
+ });
const okInputs = [1, -1, '1', '-1', Date.now()];
okInputs.forEach((input) => {
diff --git a/test/parallel/test-fs-watchfile.js b/test/parallel/test-fs-watchfile.js
index 43e2594463b9f3..f980d8f3fcc0c0 100644
--- a/test/parallel/test-fs-watchfile.js
+++ b/test/parallel/test-fs-watchfile.js
@@ -6,13 +6,23 @@ const fs = require('fs');
const path = require('path');
// Basic usage tests.
-assert.throws(function() {
- fs.watchFile('./some-file');
-}, /^Error: "watchFile\(\)" requires a listener function$/);
+common.expectsError(
+ () => {
+ fs.watchFile('./some-file');
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError
+ });
-assert.throws(function() {
- fs.watchFile('./another-file', {}, 'bad listener');
-}, /^Error: "watchFile\(\)" requires a listener function$/);
+common.expectsError(
+ () => {
+ fs.watchFile('./another-file', {}, 'bad listener');
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError
+ });
assert.throws(function() {
fs.watchFile(new Object(), common.mustNotCall());
diff --git a/test/parallel/test-fs-whatwg-url.js b/test/parallel/test-fs-whatwg-url.js
index c80fb5ca9e1512..b9aaee9c3081e6 100644
--- a/test/parallel/test-fs-whatwg-url.js
+++ b/test/parallel/test-fs-whatwg-url.js
@@ -36,9 +36,14 @@ fs.readFile(httpUrl, common.expectsError({
// pct-encoded characters in the path will be decoded and checked
fs.readFile(new URL('file:///c:/tmp/%00test'), common.mustCall((err) => {
- assert(err);
- assert.strictEqual(err.message,
- 'Path must be a string without null bytes');
+ common.expectsError(
+ () => {
+ throw err;
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: Error
+ });
}));
if (common.isWindows) {
diff --git a/test/parallel/test-fs-write-stream-throw-type-error.js b/test/parallel/test-fs-write-stream-throw-type-error.js
index 5652e9e5e697cc..42538906a5be11 100644
--- a/test/parallel/test-fs-write-stream-throw-type-error.js
+++ b/test/parallel/test-fs-write-stream-throw-type-error.js
@@ -4,12 +4,6 @@ const assert = require('assert');
const fs = require('fs');
const path = require('path');
-const numberError =
- /^TypeError: "options" must be a string or an object, got number instead\.$/;
-
-const booleanError =
- /^TypeError: "options" must be a string or an object, got boolean instead\.$/;
-
const example = path.join(common.tmpDir, 'dummy');
common.refreshTmpDir();
@@ -30,18 +24,18 @@ assert.doesNotThrow(() => {
fs.createWriteStream(example, { encoding: 'utf8' });
});
-assert.throws(() => {
- fs.createWriteStream(example, 123);
-}, numberError);
-
-assert.throws(() => {
- fs.createWriteStream(example, 0);
-}, numberError);
-
-assert.throws(() => {
- fs.createWriteStream(example, true);
-}, booleanError);
-
-assert.throws(() => {
- fs.createWriteStream(example, false);
-}, booleanError);
+const createWriteStreamErr = (path, opt) => {
+ common.expectsError(
+ () => {
+ fs.createWriteStream(path, opt);
+ },
+ {
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError
+ });
+};
+
+createWriteStreamErr(example, 123);
+createWriteStreamErr(example, 0);
+createWriteStreamErr(example, true);
+createWriteStreamErr(example, false);