diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 49edaba5b558e9..cc34e71ab1153c 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -13,6 +13,7 @@ const { StringPrototypeSlice, Symbol, SymbolDispose, + TypeError, Uint8Array, } = primordials; @@ -71,6 +72,7 @@ const { UV_ENFILE, UV_ENOENT, UV_ENOSYS, + UV_EPERM, UV_ESRCH, } = internalBinding('uv'); @@ -418,7 +420,13 @@ ChildProcess.prototype.spawn = function(options) { this._handle.close(); this._handle = null; - throw new ErrnoException(err, 'spawn'); + if (err === UV_EPERM) { + // eslint-disable-next-line no-restricted-syntax + throw new TypeError('The "shell" option must "true" when ' + + 'spawning a batch executable'); + } else { + throw new ErrnoException(err, 'spawn'); + } } else { process.nextTick(onSpawnNT, this); } diff --git a/src/process_wrap.cc b/src/process_wrap.cc index 649747fdbf2034..a88c0ee1056946 100644 --- a/src/process_wrap.cc +++ b/src/process_wrap.cc @@ -201,7 +201,7 @@ class ProcessWrap : public HandleWrap { // are not escaped (and sometimes cannot be unambiguously escaped), // hence why they are rejected here. if (IsWindowsBatchFile(options.file)) - err = UV_EINVAL; + err = UV_EPERM; // options.args Local argv_v = diff --git a/src/spawn_sync.cc b/src/spawn_sync.cc index d03803fe3abc5b..0e25d51621760a 100644 --- a/src/spawn_sync.cc +++ b/src/spawn_sync.cc @@ -770,7 +770,7 @@ Maybe SyncProcessRunner::ParseOptions(Local js_value) { // are not escaped (and sometimes cannot be unambiguously escaped), // hence why they are rejected here. if (IsWindowsBatchFile(uv_process_options_.file)) - return Just(UV_EINVAL); + return Just(UV_EPERM); Local js_args = js_options->Get(context, env()->args_string()).ToLocalChecked();