← Back to Tutorials

React App Not Starting? 7 Common Fixes for Development Servers

reactfrontenddevelopment-servernpmyarnnodejsdebuggingwebpackvitecreate-react-app

React App Not Starting? 7 Common Fixes for Development Servers

When a React development server won’t start, it’s rarely “React is broken.” It’s almost always a mismatch between your Node/npm environment, a corrupted dependency tree, a port/process conflict, a misconfigured script, or a tooling issue (Webpack/Vite/Babel/TypeScript). This tutorial walks through 7 common fixes with deep explanations and real commands you can run right now.


Before You Start: Identify What “Not Starting” Means

Different symptoms imply different root causes. Collect these details first:

  1. What command are you running?
    • Create React App (CRA): npm start or yarn start
    • Vite: npm run dev
    • Next.js (React framework): npm run dev
  2. What’s the exact error message?
  3. Does the terminal hang, crash, or exit immediately?
  4. What OS are you on (Windows/macOS/Linux)?
  5. Node and package manager versions:
    node -v
    npm -v
    yarn -v
    pnpm -v

If you’re unsure which tool you’re using, check package.json:

cat package.json

Look for scripts like "start", "dev", "serve", and dependencies like react-scripts (CRA) or vite.


Fix 1: Use a Compatible Node.js Version (and Align Tooling)

Why it breaks

React dev servers depend on a build toolchain (CRA’s react-scripts, Vite, Webpack, Babel, TypeScript). These tools often assume specific Node.js versions. If you’re on an unsupported Node version, you can see errors like:

What to do

  1. Check your Node version:
    node -v
  2. Check your project’s expected version:
    • Look for .nvmrc:
      cat .nvmrc
    • Or check engines in package.json:
      cat package.json

Fix by switching Node versions (NVM)

macOS/Linux (nvm):

nvm install 18
nvm use 18
node -v

Windows (nvm-windows):

nvm install 18.20.0
nvm use 18.20.0
node -v

If you hit OpenSSL errors (common with older Webpack)

If you’re stuck on an older toolchain and Node 17+, you may temporarily run with:

export NODE_OPTIONS=--openssl-legacy-provider
npm start

On Windows PowerShell:

$env:NODE_OPTIONS="--openssl-legacy-provider"
npm start

Better long-term fix: upgrade the build tooling (e.g., CRA/react-scripts) or use a supported Node version.


Fix 2: Clean and Reinstall Dependencies (node_modules + lockfile)

Why it breaks

A React dev server is only as stable as your dependency tree. Common causes:

Symptoms include:

The correct “clean reinstall” procedure

Pick one package manager and stick to it. Then remove node_modules and the lockfile and reinstall.

npm

rm -rf node_modules package-lock.json
npm cache verify
npm install
npm start

yarn (classic)

rm -rf node_modules yarn.lock
yarn cache clean
yarn install
yarn start

pnpm

rm -rf node_modules pnpm-lock.yaml
pnpm store prune
pnpm install
pnpm dev

Windows deletion commands

PowerShell:

Remove-Item -Recurse -Force node_modules
Remove-Item -Force package-lock.json
npm install
npm start

Why removing the lockfile helps (and when it hurts)

Team-safe approach with npm:

rm -rf node_modules
npm ci
npm start

Fix 3: Resolve Port Conflicts and Zombie Processes

Why it breaks

Dev servers bind to a port (commonly 3000 for CRA, 5173 for Vite). If another process is already using that port, your server may:

Sometimes the “other process” is actually a previous dev server that didn’t shut down cleanly.

Find what’s using the port

macOS/Linux

Check port 3000:

lsof -i :3000

Kill the process by PID:

kill -9 <PID>

Windows (PowerShell)

Find the PID:

netstat -ano | findstr :3000

Kill it:

taskkill /PID <PID> /F

Change the port explicitly

CRA

macOS/Linux:

PORT=3001 npm start

Windows PowerShell:

$env:PORT=3001
npm start

Vite

npm run dev -- --port 3001

If it starts but the browser can’t connect

Sometimes the server binds to localhost but your environment expects a different interface. You can try:

Vite:

npm run dev -- --host 0.0.0.0

CRA (less common, but possible via env):

HOST=0.0.0.0 npm start

Fix 4: Verify package.json Scripts and Project Type

Why it breaks

You might be running the wrong command for the project:

Also, scripts can be accidentally edited or broken during merges.

Inspect scripts

cat package.json

Typical examples:

CRA:

{
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test"
  }
}

Vite:

{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  }
}

Next.js:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  }
}

Fix common script issues

  1. Script missing: add it back or use the correct command.
  2. Wrong command: use npm run dev instead of npm start (Vite/Next often use dev).
  3. Local binaries not installed: if react-scripts or vite is missing, reinstall dependencies (Fix 2).

Confirm the binary exists

With npm, you can check:

ls node_modules/.bin | grep -E "react-scripts|vite|next"

On Windows PowerShell:

Get-ChildItem node_modules\.bin | Select-Object Name

If react-scripts isn’t there in a CRA project, the install is incomplete or the dependency is missing from package.json.


Fix 5: Fix Environment Variables and .env Problems

Why it breaks

React dev servers often load environment variables from .env files. A malformed .env can prevent startup, especially if:

CRA and Vite handle .env differently:

If you accidentally rely on an unexposed variable, your app might crash at runtime (white screen) or during build if used in config.

Validate .env formatting

A safe .env looks like:

REACT_APP_API_URL=https://api.example.com
REACT_APP_FEATURE_X=true

Common mistakes:

REACT_APP_API_URL = https://api.example.com   # spaces can break parsing
REACT_APP_KEY="abc"                           # quotes sometimes cause issues depending on tooling
export REACT_APP_API_URL=...                  # not valid in .env files

Debug by temporarily disabling .env

Rename it:

mv .env .env.bak
npm start

If the server starts, the issue is in your environment variables or config that reads them.

CRA vs Vite variable access

CRA:

console.log(process.env.REACT_APP_API_URL);

Vite:

console.log(import.meta.env.VITE_API_URL);

If your dev server crashes due to config reading env

Vite config runs in Node (not the browser). If you do something like:

// vite.config.js
const apiUrl = process.env.VITE_API_URL; // might be undefined depending on loading

Use Vite’s loadEnv:

import { defineConfig, loadEnv } from 'vite';

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), '');
  return {
    define: {
      __API_URL__: JSON.stringify(env.VITE_API_URL),
    },
  };
});

Fix 6: Address TypeScript/Babel/ESM Configuration Errors

Why it breaks

Modern React projects may use:

A small mismatch can stop the dev server before it even binds to a port.

Common errors:

Step 1: Check if your project is ESM

Inspect package.json:

cat package.json | grep '"type"'

If you see:

"type": "module"

then Node treats .js files as ESM. That affects config files like:

If those config files use require(...), they may crash.

Fix ESM/CommonJS config mismatches

Options:

  1. Convert config files to ESM syntax:
    import { defineConfig } from 'vite';
    export default defineConfig({ /* ... */ });
  2. Rename config files to .cjs to force CommonJS:
    • postcss.config.cjs
    • tailwind.config.cjs
    • vite.config.cjs (Vite supports this)

Example for Tailwind:

mv tailwind.config.js tailwind.config.cjs
mv postcss.config.js postcss.config.cjs

Step 2: Validate TypeScript configuration

If TypeScript compilation fails, dev servers often refuse to start (or start but show an overlay error).

Run:

npx tsc --noEmit

If you get module resolution errors, check tsconfig.json:

Also ensure your dependencies include types:

npm i -D @types/node

Step 3: Ensure Babel presets/plugins exist

If you see errors like:

Reinstall Babel dependencies or remove custom Babel config if you don’t need it. For CRA, custom Babel config is limited; CRA expects to manage Babel internally unless you eject or use overrides.

You can locate unexpected Babel configs:

ls -a | grep babel

Fix 7: Fix File Watcher Issues (Especially on Linux/WSL/Docker)

Why it breaks

Dev servers rely on file watchers to detect changes and sometimes even to complete startup. In certain environments (WSL, Docker bind mounts, network filesystems), file watching can fail or be extremely slow.

Symptoms:

Linux: Increase inotify watch limit

If you see: ENOSPC: System limit for number of file watchers reached

Run:

cat /proc/sys/fs/inotify/max_user_watches

Temporarily increase:

sudo sysctl fs.inotify.max_user_watches=524288

Persist it:

echo "fs.inotify.max_user_watches=524288" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

WSL: Prefer working inside the Linux filesystem

If your project is on /mnt/c/..., file watching can be unreliable. Move it to your WSL home directory:

mkdir -p ~/projects
cp -r /mnt/c/Users/<you>/path/to/app ~/projects/app
cd ~/projects/app
npm install
npm start

Docker: Use polling if necessary

For Webpack-based setups, polling can help. CRA supports:

CHOKIDAR_USEPOLLING=true npm start

Vite:

npm run dev -- --watch

And in vite.config.js you can configure polling:

export default {
  server: {
    watch: {
      usePolling: true,
      interval: 100,
    },
  },
};

Polling is less efficient but more reliable on mounted volumes.


A Practical Debug Flow (Use This Order)

If you want a repeatable approach, do this:

  1. Check versions
    node -v
    npm -v
  2. Run the dev command with verbose logging
    • npm:
      npm start --loglevel verbose
    • Vite:
      npm run dev -- --debug
  3. Clean reinstall
    rm -rf node_modules package-lock.json
    npm install
  4. Check port conflicts
    lsof -i :3000
  5. Temporarily remove .env
    mv .env .env.bak
  6. Validate TypeScript
    npx tsc --noEmit
  7. Fix watcher limits if on Linux/WSL/Docker

This sequence resolves the majority of “React app won’t start” cases without random guessing.


Common Error Messages and What They Usually Mean

EADDRINUSE: address already in use

Another process is using the port. Use Fix 3.

react-scripts: command not found

Dependencies not installed or react-scripts missing. Use Fix 2 and Fix 4.

ERR_OSSL_EVP_UNSUPPORTED

Node/OpenSSL mismatch with older Webpack. Use Fix 1.

Cannot use import statement outside a module

ESM/CommonJS mismatch. Use Fix 6.

ENOSPC: System limit for number of file watchers reached

Increase inotify watch limit (Fix 7).

Blank page but dev server “starts”

The dev server is running, but the app crashes in the browser. Open DevTools Console and check runtime errors. Often caused by:


Bonus: When You Need a “Nuclear Reset” (Safe Checklist)

If you’ve tried everything and want a clean baseline:

  1. Ensure correct Node version:
    node -v
  2. Remove dependencies and caches:
    rm -rf node_modules package-lock.json
    npm cache clean --force
  3. Reinstall:
    npm install
  4. Start on a different port:
    PORT=3001 npm start
  5. If still failing, capture logs to a file:
    npm start --loglevel verbose 2>&1 | tee devserver.log

Then search devserver.log for the first real error (often earlier than the last line).


Summary: The 7 Common Fixes

  1. Use a compatible Node.js version (and avoid OpenSSL/toolchain mismatches).
  2. Clean reinstall dependencies (remove node_modules + lockfile, reinstall).
  3. Resolve port conflicts (kill zombie processes or change ports).
  4. Verify package.json scripts (use the right command for CRA/Vite/Next).
  5. Fix .env and environment variables (prefix rules, formatting, config loading).
  6. Correct TypeScript/Babel/ESM configuration (module system consistency).
  7. Fix file watcher issues (inotify limits, WSL filesystem placement, Docker polling).

If you share your exact startup command, your package.json scripts, and the full terminal error output, you can usually pinpoint the root cause quickly instead of iterating blindly.