JA
/
EN

Why Commands After npm Do Not Run in Windows Batch Files and How to Use call

  • 開発環境
  • 問題解決
  • Windows

Note: The screenshots in this article were captured in a Japanese-language Windows environment. Menu and setting names may differ slightly in an English-language installation.

In a Windows batch file (.bat), commands written after npm install — for example, npm run start right after it — may not run. The Windows version of npm is actually npm.cmd, and to hand control back to the caller after running another batch/cmd file, you need to use call.

@echo off
call npm.cmd install
call npm.cmd run start

When typing directly at the command prompt, it doesn't matter whether you use call or not. You need it when you want to run a .bat or .cmd file from within another .bat/.cmd file and then continue processing afterward.

Why commands after npm are not executed

In the batch file below, processing written after npm install may not run.

@echo off
npm install
echo npm install has finished
npm run start

On Windows, running where npm shows that, depending on the environment, npm actually resolves to npm.cmd.

where npm

.cmd and .bat are batch programs. In Microsoft's official documentation for the call command, it's explained as a command used to call another batch program without stopping the parent batch program.

From the calling batch file, if you run npm.cmd without call, control passes to npm.cmd and does not return to the caller's next line once it finishes. To continue with subsequent processing, attach call.

Execution location/writing methodSubsequent processing
At the command prompt: npm installYou can continue typing as usual.
Inside a batch file: npm installIt may not return to the caller.
Inside a batch file: call npm.cmd installProceeds to the next line after completion

Basic syntax for call npm.cmd

In the batch file, writing npm.cmd including its extension makes it clearer what is being called.

@echo off
call npm.cmd install
call npm.cmd run build
call npm.cmd run start

If npm run start starts a resident process such as a server, it will not proceed to the next line until that process ends. This is not a problem with call. If you need to start the server in a separate window or process, use a separate startup method.

Why it may seem to work only the first time

If you branch the installation based on whether node_modules exists, as in the example below, the behavior can appear to change depending on how many times you've run it.

@echo off
if not exist "node_modules\" npm install
npm run start

The first time, since node_modules doesn't exist yet, npm install runs. Without call, control passes to npm.cmd and doesn't return to the caller after it finishes, so npm run start never runs.

The second time, since node_modules already exists, the npm install line is skipped. As a result, the following npm run start line runs. In other words, it isn't that "it stops working after the second time" — rather, "only the first run" ends with just npm install completing.

Attach call to both lines, as shown below.

@echo off
if not exist "node_modules\" call npm.cmd install
call npm.cmd run start

In an environment where the same dependencies need to be reproduced using package-lock.json, also consider using npm ci instead of npm install. However, installing dependencies on every boot takes time and is sensitive to network failures. In production, it's more stable to separate the deployment/update process from the application launch.

Stop processing when npm fails

call returns control to the caller, but it does not automatically stop the whole batch file if npm fails. Check errorlevel as well.

@echo off

if not exist "node_modules\" (
  call npm.cmd install
  if errorlevel 1 (
    echo npm install failed
    exit /b 1
  )
)

call npm.cmd run start
if errorlevel 1 (
  echo Failed to start the app
  exit /b 1
)

if errorlevel 1 handles the case where the exit code is 1 or greater. If you want to proceed only on success, check the error level immediately after each npm command.

When calling npx or another batch file

On Windows, npx is also usually actually npx.cmd. Likewise, attach call if there's subsequent processing.

call npx.cmd astro build
if errorlevel 1 exit /b 1

call npm.cmd run preview

The same applies when calling your own .bat or .cmd files.

call "%~dp0prepare.bat"
if errorlevel 1 exit /b 1

call "%~dp0start-app.cmd"

On the other hand, .exe files are not batch programs, so you typically don't need to add call.

When combining start and cmd /k

start can be used to open another Command Prompt window.cmd.exe /k leaves the window open after the specified command runs, while cmd.exe /c closes it after execution.

start "App" "%ComSpec%" /k call "%~dp0_start-app.bat"

The first quoted argument after start is treated as the window title, not as an executable. So in the example above, "App" is specified as the title, followed by "%ComSpec%".

designationoperation
cmd.exe /kLeaves the window open after the command runs
cmd.exe /cCloses the window after the command runs
start "App" ...Uses App as the title of the new window

Separate complex processing into separate bat files

It isn't prohibited to write multiple commands directly into cmd /k "...", and & is also an official delimiter for Windows commands. However, once path quotes, environment variables, &, and parentheses start to overlap, it becomes hard to tell which characters cmd.exe is interpreting, and how.

Long inline statements like the one below are hard to maintain and debug.

start "App" cmd.exe /k "cd /d "%PROJ%" & call npm.cmd install & call npm.cmd run start"

Separating the caller from the actual processing reduces the nesting of quotes.

The launcher, admin.bat:

@echo off
start "App" "%ComSpec%" /k call "%~dp0_start-app.bat"

The file that does the actual work, _start-app.bat:

@echo off
cd /d "%~dp0"

if not exist "node_modules\" (
  call npm.cmd install
  if errorlevel 1 exit /b 1
)

call npm.cmd run start

If you want to keep a log or close the window automatically, choose /k or /c depending on your needs.

Resolving paths based on the batch file's location

%~dp0 expands to the drive and folder path where the running batch file is located. It includes a trailing backslash.

cd /d "%~dp0"

cd /d lets you switch not only your current directory but also your drive. It's useful when launching the batch file from different working folders, such as Explorer, Startup, or Task Scheduler.

If you want to move to the parent folder, you can write it like this:

cd /d "%~dp0.."

Points to check when testing

Check the batch file you created under the following conditions.

  1. Proceeds to subsequent processing even the first time, when node_modules doesn't exist yet
  2. Also starts correctly from the second time onward, when node_modules already exists
  3. Displays an error and exits if npm fails
  4. Works even with folder paths that contain spaces
  5. Moves to the correct project folder even when started from a different working folder
  6. The window stays open if you use /k 7. The window closes after processing if you use /c If you want to see the commands being executed, temporarily remove @echo off, or display the variables and current location you need.
echo Current directory: %CD%
where npm

Reference materials

Summary

To continue processing after npm in a Windows batch file, write it as call npm.cmd .... The same applies when calling npx.cmd or your own .bat/.cmd files.

While it's possible to write complex processing directly into start and cmd /k, the interpretation of quotation marks and special characters becomes hard to follow. Separate the processing into another batch file, and fix the working folder with %~dp0 — this makes the configuration less sensitive to where it was started from.

Share this article