From 553a48bcded2975f4da360a030724c1175ad3be5 Mon Sep 17 00:00:00 2001 From: Archkon <180910180+Archkon@users.noreply.github.com> Date: Sun, 2 Aug 2026 19:58:42 +0800 Subject: [PATCH] src: return failure when task spawning fails Set a non-zero exit code and return immediately when uv_spawn() fails, since no process exit callback will be invoked. Signed-off-by: Archkon <180910180+Archkon@users.noreply.github.com> --- src/node_task_runner.cc | 2 ++ test/parallel/test-node-run.js | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/node_task_runner.cc b/src/node_task_runner.cc index 22c02e83e12e..5cafea2a13a8 100644 --- a/src/node_task_runner.cc +++ b/src/node_task_runner.cc @@ -210,6 +210,8 @@ void ProcessRunner::Run() { options_.cwd = cwd_.c_str(); if (int r = uv_spawn(loop_, &process_, &options_)) { fprintf(stderr, "Error: %s\n", uv_strerror(r)); + init_result_->exit_code_ = ExitCode::kGenericUserError; + return; } uv_run(loop_, UV_RUN_DEFAULT); diff --git a/test/parallel/test-node-run.js b/test/parallel/test-node-run.js index e24117f6b165..3af2e12587e1 100644 --- a/test/parallel/test-node-run.js +++ b/test/parallel/test-node-run.js @@ -34,6 +34,26 @@ describe('node --run [command]', () => { assert.strictEqual(child.code, 1); }); + it('returns an error when spawning the shell fails', { + skip: !common.isWindows, + }, async () => { + const env = { ...process.env }; + for (const key of Object.keys(env)) { + if (key.toLowerCase() === 'comspec') { + delete env[key]; + } + } + env.ComSpec = fixtures.path('run-script', 'non-existent-cmd.exe'); + + const child = await common.spawnPromisified( + process.execPath, + [ '--run', 'test'], + { cwd: fixtures.path('run-script'), env }, + ); + assert.match(child.stderr, /^Error: /); + assert.strictEqual(child.code, 1); + }); + it('adds node_modules/.bin to path', async () => { const child = await common.spawnPromisified( process.execPath,