diff --git a/doc/api/errors.md b/doc/api/errors.md
index 640935da35e460..b315504f9419ec 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -255,6 +255,14 @@ will affect any stack trace captured *after* the value has been changed.
If set to a non-number value, or set to a negative number, stack traces will
not capture any frames.
+
+#### error.code
+
+* {String}
+
+The `error.code` property is a string label that identifies the kind of error.
+See [Node.js Error Codes][] for details about specific codes.
+
#### error.message
* {String}
@@ -563,6 +571,16 @@ found [here][online].
encountered by [`http`][] or [`net`][] -- often a sign that a `socket.end()`
was not properly called.
+
+
+## Node.js Error Codes
+
+
+### ERR_INVALID_ARG_TYPE
+
+The `'ERR_INVALID_ARG_TYPE'` error code is used generically to identify that
+an argument of the wrong type has been passed to a Node.js API.
+
[`fs.readdir`]: fs.html#fs_fs_readdir_path_options_callback
[`fs.readFileSync`]: fs.html#fs_fs_readfilesync_file_options
[`fs.unlink`]: fs.html#fs_fs_unlink_path_callback
@@ -575,6 +593,7 @@ found [here][online].
[domains]: domain.html
[event emitter-based]: events.html#events_class_eventemitter
[file descriptors]: https://en.wikipedia.org/wiki/File_descriptor
+[Node.js Error Codes]: #nodejs-error-codes
[online]: http://man7.org/linux/man-pages/man3/errno.3.html
[stream-based]: stream.html
[syscall]: http://man7.org/linux/man-pages/man2/syscall.2.html
diff --git a/lib/events.js b/lib/events.js
index 000fa98d5a88c5..c714b47dc3e8bf 100644
--- a/lib/events.js
+++ b/lib/events.js
@@ -1,5 +1,7 @@
'use strict';
+const errors = require('internal/errors');
+
var domain;
// This constructor is used to store event handlers. Instantiating this is
@@ -61,7 +63,7 @@ EventEmitter.init = function() {
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
if (typeof n !== 'number' || n < 0 || isNaN(n))
- throw new TypeError('"n" argument must be a positive number');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'n', 'positive number');
this._maxListeners = n;
return this;
};
@@ -214,7 +216,7 @@ function _addListener(target, type, listener, prepend) {
var existing;
if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener', 'function');
events = target._events;
if (!events) {
@@ -302,7 +304,7 @@ function _onceWrap(target, type, listener) {
EventEmitter.prototype.once = function once(type, listener) {
if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener', 'function');
this.on(type, _onceWrap(this, type, listener));
return this;
};
@@ -310,7 +312,8 @@ EventEmitter.prototype.once = function once(type, listener) {
EventEmitter.prototype.prependOnceListener =
function prependOnceListener(type, listener) {
if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener',
+ 'function');
this.prependListener(type, _onceWrap(this, type, listener));
return this;
};
@@ -321,7 +324,8 @@ EventEmitter.prototype.removeListener =
var list, events, position, i, originalListener;
if (typeof listener !== 'function')
- throw new TypeError('"listener" argument must be a function');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'listener',
+ 'function');
events = this._events;
if (!events)
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index f2376f70371c60..21ddb8f1218da4 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -86,3 +86,27 @@ module.exports = exports = {
// Note: Please try to keep these in alphabetical order
E('ERR_ASSERTION', (msg) => msg);
// Add new errors from here...
+E('ERR_INVALID_ARG_TYPE', invalidArgType);
+
+function invalidArgType(name, expected, actual) {
+ const assert = lazyAssert();
+ assert(name, 'name is required');
+ assert(expected, 'expected is required');
+ var msg = `The "${name}" argument must be `;
+ if (Array.isArray(expected)) {
+ var len = expected.length;
+ expected = expected.map((i) => String(i));
+ if (len > 1) {
+ msg += `one of type ${expected.slice(0, len - 1).join(', ')}, or ` +
+ expected[len - 1];
+ } else {
+ msg = `type ${expected[0]}`;
+ }
+ } else {
+ msg = `type ${String(expected)}`;
+ }
+ if (arguments.length >= 3) {
+ msg = `. Received type ${actual !== null ? typeof actual : 'null'}`;
+ }
+ return msg;
+}
diff --git a/test/parallel/test-event-emitter-add-listeners.js b/test/parallel/test-event-emitter-add-listeners.js
index 33125daabdb3b3..a2961275b25296 100644
--- a/test/parallel/test-event-emitter-add-listeners.js
+++ b/test/parallel/test-event-emitter-add-listeners.js
@@ -69,4 +69,4 @@ assert.throws(() => {
const ee = new EventEmitter();
ee.on('foo', null);
-}, /^TypeError: "listener" argument must be a function$/);
+}, common.expectsError('ERR_INVALID_ARG_TYPE', TypeError));
diff --git a/test/parallel/test-event-emitter-max-listeners.js b/test/parallel/test-event-emitter-max-listeners.js
index 0ace154aa00a5c..1236a5035eca83 100644
--- a/test/parallel/test-event-emitter-max-listeners.js
+++ b/test/parallel/test-event-emitter-max-listeners.js
@@ -9,16 +9,13 @@ e.on('maxListeners', common.mustCall(function() {}));
// Should not corrupt the 'maxListeners' queue.
e.setMaxListeners(42);
-assert.throws(function() {
- e.setMaxListeners(NaN);
-}, /^TypeError: "n" argument must be a positive number$/);
+assert.throws(() => e.setMaxListeners(NaN),
+ common.expectsError('ERR_INVALID_ARG_TYPE', TypeError));
-assert.throws(function() {
- e.setMaxListeners(-1);
-}, /^TypeError: "n" argument must be a positive number$/);
+assert.throws(() => e.setMaxListeners(-1),
+ common.expectsError('ERR_INVALID_ARG_TYPE', TypeError));
-assert.throws(function() {
- e.setMaxListeners('and even this');
-}, /^TypeError: "n" argument must be a positive number$/);
+assert.throws(() => e.setMaxListeners('and even this'),
+ common.expectsError('ERR_INVALID_ARG_TYPE', TypeError));
e.emit('maxListeners');
diff --git a/test/parallel/test-event-emitter-once.js b/test/parallel/test-event-emitter-once.js
index 724b2ffd16aad1..57532984cb9f49 100644
--- a/test/parallel/test-event-emitter-once.js
+++ b/test/parallel/test-event-emitter-once.js
@@ -33,4 +33,4 @@ assert.throws(() => {
const ee = new EventEmitter();
ee.once('foo', null);
-}, /^TypeError: "listener" argument must be a function$/);
+}, common.expectsError('ERR_INVALID_ARG_TYPE', TypeError));
diff --git a/test/parallel/test-event-emitter-prepend.js b/test/parallel/test-event-emitter-prepend.js
index b511af9ae3691d..865ef6b21b3405 100644
--- a/test/parallel/test-event-emitter-prepend.js
+++ b/test/parallel/test-event-emitter-prepend.js
@@ -23,7 +23,7 @@ assert.throws(() => {
const ee = new EventEmitter();
ee.prependOnceListener('foo', null);
-}, /^TypeError: "listener" argument must be a function$/);
+}, common.expectsError('ERR_INVALID_ARG_TYPE', TypeError));
// Test fallback if prependListener is undefined.
const stream = require('stream');
diff --git a/test/parallel/test-event-emitter-remove-listeners.js b/test/parallel/test-event-emitter-remove-listeners.js
index dfdae52d1cf21d..651b9754568e50 100644
--- a/test/parallel/test-event-emitter-remove-listeners.js
+++ b/test/parallel/test-event-emitter-remove-listeners.js
@@ -127,7 +127,7 @@ assert.throws(() => {
const ee = new EventEmitter();
ee.removeListener('foo', null);
-}, /^TypeError: "listener" argument must be a function$/);
+}, common.expectsError('ERR_INVALID_ARG_TYPE', TypeError));
{
const ee = new EventEmitter();