Nodemon Not Restarting on File Changes? A Diagnostic Guide for Docker, WSL, and Network Mounts
Nodemon prints its watching message but never restarts on save? Diagnose watch backend mismatches on Docker/WSL/network mounts, ignore glob overreach, narrow watch paths, and exec misconfiguration.
16 Aug 2026, 23:16 UTC

The recognizable condition
Nodemon starts cleanly, prints its [nodemon] watching path(s): ... line, and your app runs — but saving a file changes nothing. No restart, no error, no log line. If you type rs in the terminal (or send SIGUSR2), the restart works fine, and you can confirm the saved content is actually visible to the process. That combination tells you something specific: nodemon and your app are healthy, but the file-watching layer never delivered the change event.
This almost always comes down to one of five causes: the watch backend doesn't work on your filesystem, an ignore pattern is swallowing the file, the watched path is too narrow, save debouncing is hiding rapid edits, or nodemon is executing the wrong entry point. The sections below walk through them in order.
Cause and diagnostic table
| Cause | Typical environment | How to confirm |
|---|---|---|
| Watch backend mismatch (inotify events never fire) | Docker volumes, WSL editing Windows files, NFS/SMB mounts, VirtualBox shared folders | Restart works with polling enabled but not in default mode |
| Ignore pattern matches the changed file | Any, often after adding broad globs like * or dist/** | File appears in the ignored list in verbose output |
--watch limited to a subpath | Monorepos, configs watching only src/ | Changes inside the watched dir restart; changes outside don't |
| Delay/debounce coalescing rapid saves | Editors with autosave, format-on-save chains | Restart happens but only after a pause, or feels intermittent |
| Exec/start script points at the wrong entry | Custom exec in nodemon.json, ts-node setups | Nodemon restarts but the old code keeps running |
Ordered checks
1. See what nodemon actually watches
Run nodemon with verbose logging from your project root (no special permissions needed):
npx nodemon --verbose server.jsThe output lists the watched paths and the ignore rules in effect. If your file's directory isn't in the watched list, or the file matches an ignore rule, you've found the problem before touching anything else.
2. Reproduce and watch for a trigger line
With verbose mode running, save a file. A working setup prints a line like [nodemon] restarting due to changes... naming the file. Silence here means the event never arrived (backend or ignore issue); a trigger line without new behavior means the exec step is the problem.
3. Audit ignore rules and watch paths
Check nodemon.json and your CLI flags together — both apply. A common trap:
{
"watch": ["src"],
"ignore": ["src/**/*.test.js", "*.log"]
}Here, edits to config/default.json at the project root will never trigger a restart because only src is watched. Ignore globs are matched broadly, so a pattern like * or **/temp/** can quietly exclude more than intended.
4. Force polling to test the backend
Nodemon's default watcher relies on OS-native events (inotify on Linux). Those events do not propagate across many virtualized or network filesystem boundaries. Test by enabling polling:
npx nodemon --legacy-watch server.js
# or in nodemon.json:
# { "legacyWatch": true }If restarts now work reliably, the backend was the issue. Polling checks files on an interval instead of waiting for events, so it works anywhere but costs CPU and I/O — acceptable on a dev machine, worth monitoring on a shared one.
5. Verify the filesystem and mount type
If polling fixes it, confirm why. Inside a Docker container, run mount | grep your-workdir or check df -T . to see the filesystem type. Bind mounts from a Windows or macOS host, NFS, and 9p/virtiofs shares commonly fail to deliver inotify events into the container. In WSL, files under /mnt/c/... have historically had unreliable file-event support; keeping the project inside the WSL filesystem (e.g., ~/projects) is the more robust fix.
Fixes tied to each finding
- Backend mismatch: keep
legacyWatch: truescoped to the affected environment — put it in a localnodemon.jsonor a docker-compose command override rather than the shared config, so teammates on native Linux keep event-based watching. - Ignore overreach: narrow the globs. Replace
"ignore": ["*"]with explicit paths like["node_modules/**", "coverage/**", "*.log"]. Re-run--verboseto confirm the file is no longer filtered. - Watch path too narrow: watch the project root, or list every directory that should trigger restarts:
"watch": ["src", "config", "server.js"]. - Rapid-save coalescing: raise the debounce:
"delay": "500"(milliseconds). This waits for a quiet period before restarting, which also helps when a formatter writes the file twice. - Wrong entry point: align nodemon with your real start command. For TypeScript, for example:
"exec": "ts-node src/index.ts"— and make sure nodemon watches.tsfiles ("ext": "ts,json"), since by default it may not restart on extensions it doesn't recognize.
Verifying the fix
Run npx nodemon --verbose ..., save a file, and confirm the restart line names that file and your app actually reloads the new code (a log line or version bump is an easy check). If you enabled polling, watch CPU with top or your container stats for a few minutes; a small project should poll cheaply, but a large tree with node_modules accidentally watched will not — that's a sign to fix your watch/ignore paths rather than accept the load.
When to escalate
Take it beyond your own config when: restarts are inconsistent across team machines with identical configs (points to mount options or Docker Desktop settings); polling causes sustained high CPU even with tight watch paths; or events are lost despite the correct backend, which can indicate exhausted inotify watch limits on Linux (cat /proc/sys/fs/inotify/max_user_watches) — raising that limit or changing the volume driver is a platform-team change, not a nodemon one.
Note that default watch behavior and config file conventions have shifted between nodemon major versions, so check your installed version (npx nodemon --version) against its changelog before assuming a flag behaves as described in older posts.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.