Skip to content

Commit 7632761

Browse files
committed
errors, child_process: migrate to using internal/errors
PR-URL: #11300 Ref: #11273 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
1 parent f0b7025 commit 7632761

10 files changed

+111
-33
lines changed

doc/api/errors.md

+61
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,27 @@ Node.js API that consumes `file:` URLs (such as certain functions in the
599599
[`fs`][] module) encounters a file URL with an incompatible path. The exact
600600
semantics for determining whether a path can be used is platform-dependent.
601601

602+
<a id="ERR_INVALID_HANDLE_TYPE"></a>
603+
### ERR_INVALID_HANDLE_TYPE
604+
605+
The '`ERR_INVALID_HANDLE_TYPE`' error code is used when an attempt is made to
606+
send an unsupported "handle" over an IPC communication channel to a child
607+
process. See [`child.send()`] and [`process.send()`] for more information.
608+
609+
<a id="ERR_INVALID_OPT_VALUE"></a>
610+
### ERR_INVALID_OPT_VALUE
611+
612+
The `'ERR_INVALID_OPT_VALUE'` error code is used generically to identify when
613+
an invalid or unexpected value has been passed in an options object.
614+
615+
<a id="ERR_INVALID_SYNC_FORK_INPUT"></a>
616+
### ERR_INVALID_SYNC_FORK_INPUT
617+
618+
The `'ERR_INVALID_SYNC_FORK_INPUT'` error code is used when a `Buffer`,
619+
`Uint8Array` or `string` is provided as stdio input to a synchronous
620+
fork. See the documentation for the [`child_process`](child_process.html)
621+
module for more information.
622+
602623
<a id="ERR_INVALID_THIS"></a>
603624
### ERR_INVALID_THIS
604625

@@ -642,6 +663,36 @@ It is currently only used in the [WHATWG URL API][] support in the [`fs`][]
642663
module (which only accepts URLs with `'file'` scheme), but may be used in other
643664
Node.js APIs as well in the future.
644665

666+
<a id="ERR_IPC_CHANNEL_CLOSED"></a>
667+
### ERR_IPC_CHANNEL_CLOSED
668+
669+
The `'ERR_IPC_CHANNEL_CLOSED'` error code is used when an attempt is made to use
670+
an IPC communication channel that has already been closed.
671+
672+
<a id="ERR_IPC_DISCONNECTED"></a>
673+
### ERR_IPC_DISCONNECTED
674+
675+
The `'ERR_IPC_DISCONNECTED'` error code is used when an attempt is made to
676+
disconnect an already disconnected IPC communication channel between two
677+
Node.js processes. See the documentation for the
678+
[`child_process`](child_process.html) module for more information.
679+
680+
<a id="ERR_IPC_ONE_PIPE"></a>
681+
### ERR_IPC_ONE_PIPE
682+
683+
The `'ERR_IPC_ONE_PIPE'` error code is used when an attempt is made to create
684+
a child Node.js process using more than one IPC communication channel.
685+
See the documentation for the [`child_process`](child_process.html)
686+
module for more information.
687+
688+
<a id="ERR_IPC_SYNC_FORK"></a>
689+
### ERR_IPC_SYNC_FORK
690+
691+
The `'ERR_IPC_SYNC_FORK'` error code is used when an attempt is made to open
692+
an IPC communication channel with a synchronous forked Node.js process.
693+
See the documentation for the [`child_process`](child_process.html)
694+
module for more information.
695+
645696
<a id="ERR_MISSING_ARGS"></a>
646697
### ERR_MISSING_ARGS
647698

@@ -674,6 +725,13 @@ kind of internal Node.js error that should not typically be triggered by user
674725
code. Instances of this error point to an internal bug within the Node.js
675726
binary itself.
676727

728+
<a id="ERR_UNKNOWN_SIGNAL"></a>
729+
### ERR_UNKNOWN_SIGNAL
730+
731+
The `'ERR_UNKNOWN_SIGNAL`' error code is used when an invalid or unknown
732+
process signal is passed to an API expecting a valid signal (such as
733+
[`child.kill()`][]).
734+
677735
<a id="ERR_UNKNOWN_STDIN_TYPE"></a>
678736
### ERR_UNKNOWN_STDIN_TYPE
679737

@@ -693,6 +751,9 @@ in user code, although it is not impossible. Occurrences of this error are most
693751
likely an indication of a bug within Node.js itself.
694752

695753

754+
[`child.kill()`]: child_process.html#child_process_child_kill_signal
755+
[`child.send()`]: child_process.html#child_process_child_send_message_sendhandle_options_callback
756+
[`process.send()`]: process.html#process_process_send_message_sendhandle_options_callback
696757
[`fs.readdir`]: fs.html#fs_fs_readdir_path_options_callback
697758
[`fs.readFileSync`]: fs.html#fs_fs_readfilesync_file_options
698759
[`fs.unlink`]: fs.html#fs_fs_unlink_path_callback

lib/internal/child_process.js

+17-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22

3+
const errors = require('internal/errors');
34
const StringDecoder = require('string_decoder').StringDecoder;
45
const EventEmitter = require('events');
56
const net = require('net');
@@ -367,6 +368,7 @@ function onErrorNT(self, err) {
367368

368369

369370
ChildProcess.prototype.kill = function(sig) {
371+
370372
const signal = sig === 0 ? sig :
371373
convertToValidSignal(sig === undefined ? 'SIGTERM' : sig);
372374

@@ -538,15 +540,15 @@ function setupChannel(target, channel) {
538540
options = undefined;
539541
} else if (options !== undefined &&
540542
(options === null || typeof options !== 'object')) {
541-
throw new TypeError('"options" argument must be an object');
543+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'Object');
542544
}
543545

544546
options = Object.assign({swallowErrors: false}, options);
545547

546548
if (this.connected) {
547549
return this._send(message, handle, options, callback);
548550
}
549-
const ex = new Error('channel closed');
551+
const ex = new errors.Error('ERR_IPC_CHANNEL_CLOSED');
550552
if (typeof callback === 'function') {
551553
process.nextTick(callback, ex);
552554
} else {
@@ -559,7 +561,7 @@ function setupChannel(target, channel) {
559561
assert(this.connected || this.channel);
560562

561563
if (message === undefined)
562-
throw new TypeError('"message" argument cannot be undefined');
564+
throw new errors.TypeError('ERR_MISSING_ARGS', 'message');
563565

564566
// Support legacy function signature
565567
if (typeof options === 'boolean') {
@@ -586,7 +588,7 @@ function setupChannel(target, channel) {
586588
} else if (handle instanceof UDP) {
587589
message.type = 'dgram.Native';
588590
} else {
589-
throw new TypeError('This handle type can\'t be sent');
591+
throw new errors.TypeError('ERR_INVALID_HANDLE_TYPE');
590592
}
591593

592594
// Queue-up message and handle if we haven't received ACK yet.
@@ -686,7 +688,7 @@ function setupChannel(target, channel) {
686688

687689
target.disconnect = function() {
688690
if (!this.connected) {
689-
this.emit('error', new Error('IPC channel is already disconnected'));
691+
this.emit('error', new errors.Error('ERR_IPC_DISCONNECTED'));
690692
return;
691693
}
692694

@@ -766,11 +768,12 @@ function _validateStdio(stdio, sync) {
766768
case 'ignore': stdio = ['ignore', 'ignore', 'ignore']; break;
767769
case 'pipe': stdio = ['pipe', 'pipe', 'pipe']; break;
768770
case 'inherit': stdio = [0, 1, 2]; break;
769-
default: throw new TypeError('Incorrect value of stdio option: ' + stdio);
771+
default:
772+
throw new errors.TypeError('ERR_INVALID_OPT_VALUE', 'stdio', stdio);
770773
}
771774
} else if (!Array.isArray(stdio)) {
772-
throw new TypeError('Incorrect value of stdio option: ' +
773-
util.inspect(stdio));
775+
throw new errors.TypeError('ERR_INVALID_OPT_VALUE',
776+
'stdio', util.inspect(stdio));
774777
}
775778

776779
// At least 3 stdio will be created
@@ -812,9 +815,9 @@ function _validateStdio(stdio, sync) {
812815
// Cleanup previously created pipes
813816
cleanup();
814817
if (!sync)
815-
throw new Error('Child process can have only one IPC pipe');
818+
throw new errors.Error('ERR_IPC_ONE_PIPE');
816819
else
817-
throw new Error('You cannot use IPC with synchronous forks');
820+
throw new errors.Error('ERR_IPC_SYNC_FORK');
818821
}
819822

820823
ipc = new Pipe(true);
@@ -849,15 +852,14 @@ function _validateStdio(stdio, sync) {
849852
} else if (isUint8Array(stdio) || typeof stdio === 'string') {
850853
if (!sync) {
851854
cleanup();
852-
throw new TypeError('Asynchronous forks do not support ' +
853-
'Buffer, Uint8Array or string input: ' +
854-
util.inspect(stdio));
855+
throw new errors.TypeError('ERR_INVALID_SYNC_FORK_INPUT',
856+
util.inspect(stdio));
855857
}
856858
} else {
857859
// Cleanup
858860
cleanup();
859-
throw new TypeError('Incorrect value for stdio stream: ' +
860-
util.inspect(stdio));
861+
throw new errors.TypeError('ERR_INVALID_OPT_VALUE', 'stdio',
862+
util.inspect(stdio));
861863
}
862864

863865
return acc;

lib/internal/errors.js

+16-1
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,32 @@ E('ERR_INVALID_ARG_TYPE', invalidArgType);
9191
E('ERR_INVALID_CALLBACK', 'callback must be a function');
9292
E('ERR_INVALID_FILE_URL_HOST', 'File URL host %s');
9393
E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s');
94+
E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent');
95+
E('ERR_INVALID_OPT_VALUE',
96+
(name, value) => {
97+
return `The value "${String(value)}" is invalid for option "${name}"`;
98+
});
99+
E('ERR_INVALID_SYNC_FORK_INPUT',
100+
(value) => {
101+
return 'Asynchronous forks do not support Buffer, Uint8Array or string' +
102+
`input: ${value}`;
103+
});
94104
E('ERR_INVALID_THIS', 'Value of "this" must be of type %s');
95105
E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple');
96106
E('ERR_INVALID_URL', 'Invalid URL: %s');
97107
E('ERR_INVALID_URL_SCHEME',
98108
(expected) => `The URL must be ${oneOf(expected, 'scheme')}`);
109+
E('ERR_IPC_CHANNEL_CLOSED', 'channel closed');
110+
E('ERR_IPC_DISCONNECTED', 'IPC channel is already disconnected');
111+
E('ERR_IPC_ONE_PIPE', 'Child process can have only one IPC pipe');
112+
E('ERR_IPC_SYNC_FORK', 'IPC cannot be used with synchronous forks');
99113
E('ERR_MISSING_ARGS', missingArgs);
100114
E('ERR_STDERR_CLOSE', 'process.stderr cannot be closed');
101115
E('ERR_STDOUT_CLOSE', 'process.stdout cannot be closed');
116+
E('ERR_UNKNOWN_BUILTIN_MODULE', (id) => `No such built-in module: ${id}`);
117+
E('ERR_UNKNOWN_SIGNAL', (signal) => `Unknown signal: ${signal}`);
102118
E('ERR_UNKNOWN_STDIN_TYPE', 'Unknown stdin file type');
103119
E('ERR_UNKNOWN_STREAM_TYPE', 'Unknown stream file type');
104-
E('ERR_UNKNOWN_BUILTIN_MODULE', (id) => `No such built-in module: ${id}`);
105120
// Add new errors from here...
106121

107122
function invalidArgType(name, expected, actual) {

lib/internal/util.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22

3+
const errors = require('internal/errors');
34
const binding = process.binding('util');
45
const signals = process.binding('constants').os.signals;
56

@@ -177,7 +178,7 @@ function convertToValidSignal(signal) {
177178
if (signalName) return signalName;
178179
}
179180

180-
throw new Error('Unknown signal: ' + signal);
181+
throw new errors.Error('ERR_UNKNOWN_SIGNAL', signal);
181182
}
182183

183184
function getConstructorOf(obj) {

test/parallel/test-child-process-constructor.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
require('../common');
3+
const common = require('../common');
44
const assert = require('assert');
55
const { ChildProcess } = require('child_process');
66
assert.strictEqual(typeof ChildProcess, 'function');
@@ -64,6 +64,6 @@ assert(Number.isInteger(child.pid));
6464
// try killing with invalid signal
6565
assert.throws(() => {
6666
child.kill('foo');
67-
}, /^Error: Unknown signal: foo$/);
67+
}, common.expectsError({ code: 'ERR_UNKNOWN_SIGNAL' }));
6868

6969
assert.strictEqual(child.kill(), true);

test/parallel/test-child-process-send-type-error.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const cp = require('child_process');
66
function fail(proc, args) {
77
assert.throws(() => {
88
proc.send.apply(proc, args);
9-
}, /"options" argument must be an object/);
9+
}, common.expectsError({code: 'ERR_INVALID_ARG_TYPE', type: TypeError}));
1010
}
1111

1212
let target = process;

test/parallel/test-child-process-spawnsync-kill-signal.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ if (process.argv[2] === 'child') {
2121
// Verify that an error is thrown for unknown signals.
2222
assert.throws(() => {
2323
spawn('SIG_NOT_A_REAL_SIGNAL');
24-
}, /Error: Unknown signal: SIG_NOT_A_REAL_SIGNAL/);
24+
}, common.expectsError({ code: 'ERR_UNKNOWN_SIGNAL' }));
2525

2626
// Verify that the default kill signal is SIGTERM.
2727
{

test/parallel/test-child-process-spawnsync-validation-errors.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ if (!common.isWindows) {
185185
{
186186
// Validate the killSignal option
187187
const typeErr = /^TypeError: "killSignal" must be a string or number$/;
188-
const unknownSignalErr = /^Error: Unknown signal:/;
188+
const unknownSignalErr =
189+
common.expectsError({ code: 'ERR_UNKNOWN_SIGNAL' });
189190

190191
pass('killSignal', undefined);
191192
pass('killSignal', null);

test/parallel/test-child-process-stdio.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,4 @@ assert.deepStrictEqual(options, {stdio: 'ignore'});
4242

4343
assert.throws(() => {
4444
common.spawnPwd({stdio: ['pipe', 'pipe', 'pipe', 'ipc', 'ipc']});
45-
}, /^Error: Child process can have only one IPC pipe$/);
45+
}, common.expectsError({code: 'ERR_IPC_ONE_PIPE', type: Error}));

test/parallel/test-child-process-validate-stdio.js

+8-10
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
'use strict';
22
// Flags: --expose_internals
33

4-
require('../common');
4+
const common = require('../common');
55
const assert = require('assert');
66
const _validateStdio = require('internal/child_process')._validateStdio;
77

8+
const expectedError =
9+
common.expectsError({code: 'ERR_INVALID_OPT_VALUE', type: TypeError});
10+
811
// should throw if string and not ignore, pipe, or inherit
9-
assert.throws(function() {
10-
_validateStdio('foo');
11-
}, /Incorrect value of stdio option/);
12+
assert.throws(() => _validateStdio('foo'), expectedError);
1213

1314
// should throw if not a string or array
14-
assert.throws(function() {
15-
_validateStdio(600);
16-
}, /Incorrect value of stdio option/);
15+
assert.throws(() => _validateStdio(600), expectedError);
1716

1817
// should populate stdio with undefined if len < 3
1918
{
@@ -27,9 +26,8 @@ assert.throws(function() {
2726

2827
// should throw if stdio has ipc and sync is true
2928
const stdio2 = ['ipc', 'ipc', 'ipc'];
30-
assert.throws(function() {
31-
_validateStdio(stdio2, true);
32-
}, /You cannot use IPC with synchronous forks/);
29+
assert.throws(() => _validateStdio(stdio2, true),
30+
common.expectsError({code: 'ERR_IPC_SYNC_FORK', type: Error}));
3331

3432
{
3533
const stdio3 = [process.stdin, process.stdout, process.stderr];

0 commit comments

Comments
 (0)