Troubleshooting

vite: command not found? Run the local binary the right way

Run npm install, then npm run dev or npx vite: Vite lives in node_modules/.bin, not on PATH. Fixes sh: 1: vite: not found in Docker and CI, and on Windows.

Published · Updated ~8 min read
On this page

Short answer: Vite is not a global program. It is a per-project dependency, and npm install puts its executable in node_modules/.bin inside the project. Your shell’s PATH does not include that folder, so typing vite at the prompt fails while npm run dev works: package-manager scripts add node_modules/.bin to the PATH for as long as they run.

If npm run dev itself fails with sh: vite: command not found, sh: 1: vite: not found or, on Windows, 'vite' is not recognized as an internal or external command, then Vite is not in node_modules at all. In most cases the dependencies were never installed. In the folder that contains package.json:

any shell · project folder
npm install
npm run dev

With pnpm or yarn, run pnpm install or yarn install instead. If the error survives the install, find your message below.

Which error do you see?

npm runs scripts with /bin/sh on Linux and macOS and with cmd.exe on Windows, so the same problem reads differently on each system:

MessageWhere it appearsCause and fix
zsh: command not found: vite or bash: vite: command not foundYou typed vite in a terminalNormal, the shell does not search node_modules/.bin: run the local Vite
sh: vite: command not foundnpm run on macOS (sh is bash 3.2) and on RHEL 8 (bash 4.4)Vite missing from node_modules: why
sh: line 1: vite: command not foundnpm run on Fedora, RHEL 9 and 10, Arch (sh is bash 5.1 or newer)The same: why
sh: 1: vite: not foundnpm run on Debian, Ubuntu, Ubuntu CI runners, Debian-based node images (sh is dash)The same, often skipped devDependencies: why, servers and CI
sh: vite: not foundnpm run in node:*-alpine images (BusyBox sh)Docker, docker compose
'vite' is not recognized as an internal or external command,npm run dev on Windows (cmd.exe)Windows
vite : The term 'vite' is not recognized as the name of a cmdletYou typed vite in PowerShellRun the local Vite
sh: 1: vite: Permission deniednpm run, after copying node_modulesExecute bit lost
Need to install the following packages:npx vite in a project without a local ViteAnswer no, install the project’s dependencies: npx

Find out which case you have

bash · zsh · project folder
ls node_modules/.bin/vite     # is the binary there?
npm ls vite                   # is it declared and installed?
npm config get omit           # "dev" means devDependencies are skipped
  • The binary exists: you only need to run it through the package manager (below).
  • No node_modules folder: dependencies were never installed. Run npm install.
  • node_modules exists, Vite is missing: npm ls vite prints (empty). Either it is not in package.json, or devDependencies were skipped; npm config get omit answering dev confirms the second. See why Vite is missing.

Run the local Vite, not a global one

Every package manager has a way to run a binary from the project’s own node_modules:

any shell · npm
npx vite
any shell · pnpm
pnpm exec vite
any shell · yarn
yarn vite
any shell · bun
bunx vite

pnpm vite works too. Subcommands follow the same pattern: npx vite build, npx vite preview.

When the project has no local copy, npx asks first:

npx output
Need to install the following packages:
vite@8.3.4
Ok to proceed? (y)

Yarn 2 and later in Plug’n’Play mode create no node_modules at all, so there is no .bin folder for npx to find. Run Vite with yarn vite or your yarn dev script.

Better: use package.json scripts

Projects created with npm create vite@latest already contain these scripts. If yours does not, add them. Everyone on the team, and your CI, then runs the same command with the same Vite version.

package.json
{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  }
}
any shell
npm run dev
npm run build

npm run dev says “vite: not found”: why Vite is missing

npm runs each script with /bin/sh and puts node_modules/.bin of the project, and of every folder above it, on that shell’s PATH. When the script still cannot find vite, the file is not there. The usual reasons:

  • Dependencies were never installed: a fresh clone, or a deleted node_modules.
  • Vite is not in package.json: npm install -D vite adds it.
  • devDependencies were skipped. Vite is a devDependency, and npm leaves those out when NODE_ENV=production is set, with --omit=dev, or with omit=dev in an .npmrc. A NODE_ENV exported in your own shell profile does it on your laptop, too.
  • bin-links is off. With bin-links=false in an .npmrc, or --no-bin-links (common on shared folders without symlinks, such as VirtualBox or Vagrant mounts), npm installs the packages but creates no .bin entries.
  • Another folder. The install ran in one directory and the script in another: a monorepo package, a CI job with a different working directory, or a hosting dashboard whose “base directory” points elsewhere.
bash · zsh
echo "$NODE_ENV"
npm config get omit
npm config get bin-links

Fix the setting where it comes from (shell profile, .npmrc, CI variables), then install again with devDependencies:

bash · zsh
rm -rf node_modules
npm install --include=dev

--include=dev wins over NODE_ENV=production and omit=dev. For a new project, npm create vite@latest scaffolds everything, including the scripts above.

On a server, in Docker and in CI

This is where the error usually shows up, during npm run build, as sh: 1: vite: not found. Build servers and Dockerfiles often set NODE_ENV=production or install with --omit=dev, so Vite never arrives. Install everything needed to build, build, then serve the output:

Linux · build server
npm ci --include=dev
npm run build
# serve the static output in dist/ with nginx or any web server

If npm ci itself stops on a fresh server with gyp ERR! stack Error: not found: make, a dependency is compiling a native addon and the box has no toolchain yet. See make: command not found for the build tools to install.

In Docker, a multi-stage build installs everything needed to build, then ships only the finished files:

Dockerfile
FROM node:24-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html

Add node_modules to .dockerignore, so COPY . . does not copy your own folder over the one npm ci built inside the image.

docker compose: the bind mount hides node_modules

A development setup that mounts the project into the container with .:/app replaces everything under /app, including the node_modules the image installed, with your host folder. If the host has none, npm run dev in the container fails with sh: vite: not found. An extra anonymous volume keeps the container’s own copy:

compose.yaml
services:
  web:
    build:
      context: .
      target: build
    command: npm run dev -- --host
    ports:
      - "5173:5173"
    volumes:
      - .:/app
      - /app/node_modules

target: build picks the Node stage of the Dockerfile above; the final nginx stage has no Node, so npm itself would be missing there. --host makes the dev server listen on all interfaces, which the port mapping needs. After changing dependencies, rebuild with docker compose up --build --renew-anon-volumes so the volume is filled from the new image.

Windows: “'vite' is not recognized”

On Windows, npm runs scripts with cmd.exe, so the same failure reads:

cmd · example output
'vite' is not recognized as an internal or external command,
operable program or batch file.

The cause is the same as sh: vite: not found: node_modules\.bin\vite.cmd does not exist. Run npm install in the folder that contains package.json, and check that your terminal, often the one inside VS Code, is open in that folder and not one level above it.

Typing vite straight into PowerShell gives The term 'vite' is not recognized as the name of a cmdlet, function, script file, or operable program. (PowerShell 7: “as a name of a cmdlet… or executable program”). That is the shell not searching node_modules: use npm run dev or npx vite. If PowerShell instead refuses to run npm.ps1 or npx.ps1 because running scripts is disabled, that is its execution policy; the fix is in npx: command not found.

One Windows-specific trap: a node_modules folder installed on Windows does not work inside WSL or a Linux container, and the reverse is also true. Vite’s build tools include platform-specific native binaries. Delete node_modules and install again on the system that runs the build.

“vite: Permission denied”

sh: 1: vite: Permission denied means the file exists but has lost its execute bit. That typically happens after node_modules was copied from another machine, unpacked from a zip, or placed on a noexec mount. A clean reinstall is the reliable fix:

bash · zsh
rm -rf node_modules
npm ci          # or npm install if there is no lockfile

More on execute bits and noexec mounts: bash: Permission denied.

Should you install Vite globally?

npm install -g vite makes the bare vite command work, but it runs one global version against every project. When a project pins a different major version, or plugins that expect one, you get confusing build failures. Keep Vite local and run it through scripts or npx.

When the error changes after the fix

If Vite now starts but crashes straight away with a syntax error or a message about your Node.js version, the Node install is too old for the Vite release. Vite 8.3 needs Node 20.19 or newer within 20.x, or 22.12 and later (per npm view vite engines, checked 11 Oct 2026). The nodejs packages of Debian 12 (18.20) and Ubuntu 24.04 (18.19) are too old; Debian 13 (20.19) and Ubuntu 26.04 (22.22) are recent enough. Compare node --version with npm view vite engines. If Node or npx is missing entirely, see npx: command not found.

Check that it works

any shell · project folder
npm ls vite
npx vite --version

npm ls vite should list a vite@ version instead of (empty), and npx vite --version should print that version without offering a download. Then npm run dev starts the dev server, on http://localhost:5173/ unless your config picks another port.

Vite 8 bundles with Rolldown, which uses several cores, but JavaScript plugins and a tsc type check still run on one. If slow builds on a shared server get in your way, the Hi-CPU KVM line is the AMD EPYC plan sized for work that leans on one or two cores rather than many.

Another tool missing, or a directory to add to PATH for good in bash, zsh and fish? See command not found: the three causes and the fix for every tool.

Frequently asked

What does 'sh: 1: vite: not found' mean?

npm ran your script with /bin/sh (dash on Debian, Ubuntu, Debian-based Docker images and Ubuntu CI runners) and found no vite in node_modules/.bin. The dependencies were not installed, devDependencies were skipped because NODE_ENV=production or --omit=dev was set, or the install ran in another folder. Run 'npm ci --include=dev' in the folder with package.json, then 'npm run build'.

How do I fix 'vite is not recognized as an internal or external command' on Windows?

npm runs scripts with cmd.exe on Windows, and the message means Vite is not installed in the project. Open the terminal in the folder that contains package.json, run 'npm install', then 'npm run dev'. If node_modules was copied from WSL, Linux or a Mac, delete it and install again on Windows.

Why does 'npm run dev' work but typing 'vite' does not?

Vite lives in the project's node_modules/.bin, which is not on your shell's PATH. npm, pnpm and yarn add that folder to the PATH while a script runs. Use 'npx vite' or the package.json scripts rather than a global install, which ignores the version each project pins.

Related articles

All troubleshooting