Introducing Process Warnings in Node v6

James M Snell
3 min readMar 24, 2016

--

A few minutes ago I landed Pull Request https://github.com/nodejs/node/pull/4782 into the Node.js master branch. This pull request introduces a brand new “process warning” API. Specifically it adds one new `emitWarning()` method to Node.js’ global `process` object and a new `process.on(‘warning’)` event.

$ node
> process.emitWarning('something strange happened');
undefined
> (node:7795) Warning: something strange happened

By default, whenever a warning is issued using `process.emitWarning()`, Node.js will print that warning to stderr on `process.nextTick()`. The process object will also emit the new `warning` event passing the warning off to listening callbacks:

$ node
> process.on('warning', (warning) => {
... console.log(warning.name);
... console.log(warning.message);
... console.log(warning.stack);
... });
...
> process.emitWarning('something strange happened');
undefined
> (node:7795) Warning: something strange happened
Warning
something strange happened
Warning: something strange happened
at repl:1:9
at REPLServer.defaultEval (repl.js:271:27)
at bound (domain.js:280:14)
at REPLServer.runBound [as eval] (domain.js:293:12)
at REPLServer.<anonymous> (repl.js:441:12)
at emitOne (events.js:95:20)
at REPLServer.emit (events.js:182:7)
at REPLServer.Interface._onLine (readline.js:216:10)
at REPLServer.Interface._line (readline.js:555:8)
at REPLServer.Interface._ttyWrite (readline.js:832:14)

In prior versions, Node.js would simply print warnings directly to stderr. For instance, anyone familiar with using EventEmitters in Node.js is likely familiar with warning that is printed to stderr whenever too many listeners are added for a given event.

For instance, running the following code on Node.js v5:

‘use strict’;
const EventEmitter = require(‘events’);
class MyEE extends EventEmitter {
constructor() {
super();
this.setMaxListeners(2);
}
}
const myEE = new MyEE();
myEE.on(‘foo’, () => {});
myEE.on(‘foo’, () => {});
myEE.on(‘foo’, () => {});

Would output:

(node) warning: possible EventEmitter memory leak detected. 3 foo listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
at MyEE.addListener (events.js:252:17)
at Object.<anonymous> (myscript.js:15:6)
at Module._compile (module.js:413:34)
at Object.Module._extensions..js (module.js:422:10)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Function.Module.runMain (module.js:447:10)
at startup (node.js:139:18)
at node.js:999:3

This message and trace are printed directly to stderr. There is nothing your application code can do to respond to or detect this warning and there is no way for you to disable the output being sent to stderr.

Running this same code in Node.js v6 will generate the following by default:

(node:8032) Warning: Possible EventEmitter memory leak detected. 3 foo listeners added. Use emitter.setMaxListeners() to increase limit

The Node.js process object will also emit the `warning` event, which, when combined with the new ` — no-warnings` command line flag, will allow a developer to suppress the default stderr output and handle the warning in a custom way, for instance:

‘use strict’;
const EventEmitter = require(‘events’);
const MyLogger = getThirdPartyLoggingToolSomehow();
process.on(‘warning’, (warning) => {
MyLogger.warn(warning);
});
class MyEE extends EventEmitter {
constructor() {
super();
this.setMaxListeners(2);
}
}
const myEE = new MyEE();
myEE.on(‘foo’, () => {});
myEE.on(‘foo’, () => {});
myEE.on(‘foo’, () => {});

Then run with:

$ node --no-warnings myscript.js

The warning emitted by Node.js will be redirected to the third party logging module rather than printing to stderr.

All warnings have a name, a message, and a stack trace. By default, when Node.js prints the warning to stderr, it will omit the stack trace. To have Node.js show the stack, simply use the ` — trace-warnings` command line flag:

$ node --trace-warnings myscript.js
(node:8151) Warning: Possible EventEmitter memory leak detected. 3 foo listeners added. Use emitter.setMaxListeners() to increase limit
at MyEE.addListener (events.js:248:17)
at Object.<anonymous> (myscript.js:15:6)
at Module._compile (module.js:417:34)
at Object.Module._extensions..js (module.js:426:10)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Function.Module.runMain (module.js:451:10)
at startup (node.js:155:18)
at node.js:433:3

Deprecation Warnings

Node.js v6 now uses `process.emitWarning()` to emit Deprecation Warnings whenever a developer uses a deprecated API or feature. The existing ` — no-deprecation`, ` — throw-deprecation` and ` — trace-deprecation` command line flags are still supported and continue to work as expected. However, the ` — no-warnings` command line flag takes precedence over ` — no-deprecation` and will suppress notification of all deprecation warnings. Likewise, the ` — trace-warnings` flag takes precedence over ` — trace-deprecation`.

Emitting Custom Warnings

The process warning API has been specifically designed to allow userland modules to issue their own warnings using the `process.emitWarning()` method.

$ node --no-warnings
> process.on('warning', (warning) => {
... console.log(warning.name.toUpperCase());
... });
> process.emitWarning('something happened', 'MyWarning');
undefined
> MYWARNING

The first argument passed to `process.emitWarning()` is the warning message. The second argument passed is the warning name. Note that by using `DeprecationWarning` as the warning name, your code can issue it’s own Deprecation Warnings that are handled automatically in the same way as Node.js’ own deprecations (Developers already using the Node.js util.deprecate() method get this automatically).

Note that when the ` — no-warnings` command line flag is used, the process object still emits the warning event but the default output to stderr is skipped.

--

--