Fix: No loader is configured for ".node" files (Vite)
Trace the import that brings a native addon into the dev scan, and distinguish the tested Vite 4 behaviour from newer bundlers.
TL;DR#
This article covers the esbuild-based Vite 4.1.0 incident reproduced below. When its dependency scan reaches the native-addon import in fsevents, esbuild has no configured loader for the .node file. Remove an accidental import of development tooling from application code, or exclude the native watcher from the development optimiser:
// vite.config.js
export default {
optimizeDeps: { exclude: ['fsevents'] },
}Vite 8 uses Rolldown for dependency pre-bundling and production builds. The older scanner architecture and process-exit behaviour below are not universal properties of current Vite.
The error#
✘ [ERROR] No loader is configured for ".node" files: node_modules/fsevents/fsevents.node
node_modules/fsevents/fsevents.js:2:23:
2 │ const Native = require("./fsevents.node");
╵ ~~~~~~~~~~~~~~~~~
Error: Build failed with 1 error:
node_modules/fsevents/fsevents.js:2:23: ERROR: No loader is configured for ".node" files: node_modules/fsevents/fsevents.node
at failureErrorWithLog (/work/repro/node_modules/esbuild/lib/main.js:1604:15)The reported Vite 4.1.0 process terminated during the dependency scan with this error. This is Stack Overflow question 75640753, filed against a React tutorial project. Reinstalling dependencies did not resolve the reporter's failure. Inspect the import path that reaches the native addon rather than assuming the package download is corrupt.
Do not generalise that termination behaviour to other versions. Vite 8.3.5 catches dependency-scan failures and can continue serving HTTP while skipping pre-bundling. An HTTP 200 therefore does not prove the scan succeeded. If the child diagnostic points into generated documentation HTML, see the unwanted Vite scan-entry diagnosis.
Why it happens#
fsevents is a native macOS file-watching binding. Its own package.json on the npm registry restricts it to one platform:
"os": ["darwin"]npm normally skips an optional package whose platform restriction does not match: its installer checks the platform before extraction. The synthetic reproduction below deliberately supplies the package files; it does not reproduce npm installing fsevents on Linux. Inspect the actual files and import chain in your failing project instead of inferring how they arrived from the error alone.
In Vite 4, the dependency optimiser (optimizeDeps) uses esbuild to analyse the dependency graph for development — see the versioned dependency pre-bundling documentation. When this scan reaches fsevents/fsevents.js, it encounters require("./fsevents.node") without a configured native-addon loader. That is a static-analysis failure before anything attempts to execute the binary; it is not evidence that esbuild parsed the binary as JavaScript.
This is reproducible with a minimal Vite project: planting a fsevents package whose fsevents.js requires a fsevents.node file, with no other config, makes npx vite crash on startup with this exact message — reproduced on Vite 4.1.0, Node 20, 8 October 2026, in a throwaway container with no macOS toolchain involved anywhere. The binary itself never has to be a real, loadable native addon for the crash to happen: esbuild fails while parsing the require() call during its static dependency graph walk, before Node ever attempts to dlopen anything.
VITE v4.1.0 ready in 161 ms
➜ Local: http://localhost:5191/
✘ [ERROR] No loader is configured for ".node" files: node_modules/fsevents/fsevents.nodeFix#
1. Exclude fsevents from the dependency optimizer#
In vite.config.js (or .ts):
import { defineConfig } from 'vite'
export default defineConfig({
optimizeDeps: {
exclude: ['fsevents'],
},
})Restart the dev server. In the same reproduction, adding only this block turns the crash into a clean start:
VITE v4.1.0 ready in 153 ms
➜ Local: http://localhost:5192/2. If it's your own code importing fsevents#
Two other answers on the same thread trace the import to something unrelated to any explicit fsevents usage. One reporter found that "vscode had accidentally imported the mergeAlias method from vitejs somewhere in my project" — an editor auto-import had silently added an import from one of Vite's own internal paths, which pulls in Vite's dev-only chokidar → fsevents chain the same way the dev server itself does. Another describes the identical mistake with a different symbol: "an auto import import {sortUserPlugins} from 'vite'; for no reason other than to spoil my afternoon." Neither import was intentional, and neither referenced fsevents by name — the editor's autocomplete added a Vite-internal import, and that import is what dragged the scanner into fsevents. Search your diff (or grep -rn "from 'vite'" src/) for any import from the vite package itself in application code outside vite.config.js — that is almost never correct, and removing it fixes the scan without touching optimizeDeps at all.
3. Confirm the package is actually optional#
If fsevents is a direct dependency in your own package.json rather than something hoisted in transitively, remove it unless you specifically need macOS file-watching behaviour in that exact package — it has no effect anywhere else and only exists to be caught by scans like this one. Pinning it to an old major version, as the original question's package.json did with "resolutions": { "**/**/fsevents": "^1.2.9" }, does not help either: the scanner fails on the require("./fsevents.node") line regardless of which fsevents version supplies it, because the failure is about the file extension esbuild sees, not about the package's behaviour.
Verify the fix#
Delete the dependency cache and restart clean, so a stale pre-bundle doesn't hide whether the fix actually took:
rm -rf node_modules/.vite
npm run devRelevant configuration changes invalidate Vite's dependency cache, as the caching documentation explains. Removing node_modules/.vite above is an explicitly forced diagnostic reset, not a requirement for Vite to notice the exclusion. The saved Vite 4.1.0 reproduction failed before the exclusion and then started without that scanner error after it was added:
VITE v4.1.0 ready in 153 ms
➜ Local: http://localhost:5192/One email a month — the latest explained errors
What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.
Why rollupOptions.external alone doesn't fix this#
For Vite 4, build.rollupOptions.external configures the production bundler; optimizeDeps configures development dependency optimisation. The Vite 4 build options and dependency options document those separate responsibilities. This is a documentation-based distinction: the saved reproduction does not contain an external-only experiment. Configure the step named by the failure, and check the documentation for the installed Vite generation.
If a later build instead fails with Could not resolve "/src/main.tsx" or a similar Rollup entry-resolution error, that's a different cause — see Fix Rollup failed to resolve import "/src/main.tsx" in Vite for the index.html placement issue behind that one.
On Windows specifically, the next common Vite dependency error looks different again — a missing platform binary rather than a rejected one. See Fix Cannot find module @rollup/rollup-win32-x64-msvc if node_modules was installed on one OS and run on another.
And if the failure is in vite.config.ts itself rather than in a dependency scan — Cannot find module '@vitejs/plugin-react' or similar — that's a TypeScript resolution issue, covered in Fix Cannot find module '@vitejs/plugin-react' in Vite.
For this Vite 4 incident, the relevant distinction is the development dependency scan versus the production bundle. On newer Vite releases, identify the installed version and the underlying diagnostic before assuming the same implementation or recovery behaviour. Keep native development tooling out of browser application imports, and verify the particular operation that originally failed.
Further reading: Vite entry module (index.html): fix .dockerignore. Also see Chrome hangs with Vite dev server: raise the file limit. Also see Expected identifier but found "import" (define name) in Vite.
Frequently Asked Questions
Still stuck? Paste your error.
Paste the error message or stack trace — we check it against every fix and tool on the site.
Continue Reading
Fix Vite 'Top-level await is not available' build error
Why vite dev works but vite build fails on a top-level await, which setting fixes the build and which one only fixes dev, reproduced on Vite 2.9, 5.4, 7.3 and 8.3.
Vite build Unexpected token in node_modules: fix define
Why vite build fails on react-router-dom while vite dev works, which define line triggers it, and a polyfill setup that builds, reproduced on Vite 2.9.12.
Fix Vite: crypto.hash is not a function
Check the Node binary that actually starts Vite, distinguish API availability from the supported version range, and verify the fix without replacing the lockfile.


