nodejs-errors.dev

Node.js Error Reference

Exact causes, step-by-step fixes, and code examples for the most common Node.js runtime errors.

Module Resolution

Error: Cannot find module
Thrown by require() when it cannot locate an npm package or local file. The most common Node.js error — caused by missing npm install, typos, wrong paths, TypeScript aliases, or Docker misconfigurations.
View causes & fixes →
ERR_PACKAGE_PATH_NOT_EXPORTED
Thrown when importing a subpath (e.g. pkg/lib/utils) that is not listed in the package's "exports" field in package.json. Common after upgrading packages that added a strict exports map.
View causes & fixes →
ERR_REQUIRE_ESM
Thrown when require() is used to load a pure ES module package. Increasingly common as popular packages like chalk, node-fetch, and nanoid drop CommonJS support.
View causes & fixes →
ERR_REQUIRE_ASYNC_MODULE
Thrown on Node.js 20.19+ / 22.12+ when require() is called on an ES module whose graph contains a top-level await. The synchronous loader cannot evaluate an async module. Fix with dynamic import(), remove the top-level await, or convert the caller to ESM. Use --experimental-print-required-tla to find the offending file. Affects lru-cache v11.3.0, firebase-tools, and jsdom with certain dependency versions.
View causes & fixes →
SyntaxError: Cannot use import statement outside a module
Thrown when import or export syntax is used in a file Node.js treats as CommonJS. Fix by adding "type": "module" to package.json, renaming the file to .mjs, or replacing import with require(). Also covers SyntaxError: Unexpected token 'export'.
View causes & fixes →
ERR_UNSUPPORTED_DIR_IMPORT
Thrown when an ESM import targets a directory instead of a specific file. CommonJS resolved ./utils to ./utils/index.js; ESM forbids this. Fix with explicit extensions (./utils/index.js), a package.json exports map, or TypeScript moduleResolution: "node16". The --experimental-specifier-resolution=node flag was removed in Node.js 19.
View causes & fixes →
ERR_DLOPEN_FAILED
Thrown when Node.js cannot load a native addon (.node file) because it was compiled for a different NODE_MODULE_VERSION. Common after upgrading Node.js or on Apple Silicon when an x86_64 binary is loaded under arm64. Fix with npm rebuild, a clean reinstall, or electron-rebuild for Electron. Affects bcrypt, sharp, canvas, sqlite3.
View causes & fixes →
ERR_UNKNOWN_FILE_EXTENSION
Thrown as TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" when Node.js's ESM loader encounters a file extension it cannot execute — overwhelmingly .ts TypeScript files when "type": "module" is set in package.json. Modern fixes: tsx (zero config), node --experimental-strip-types (Node 22.6+), or native execution (Node 23.6+). Also covers .tsx, .json5, .wasm, and the Node 22.14 regression.
View causes & fixes →
ERR_INVALID_PACKAGE_CONFIG
Thrown when Node.js reads a package.json that is malformed JSON (trailing commas, comments, single quotes) or has an invalid "exports", "imports", or "type" field. The most common structural error: mixing subpath keys ("./utils") and condition keys ("import", "require") at the same exports object level. Also fires on empty or corrupted package.json files in node_modules.
View causes & fixes →

File System

ENOENT: no such file or directory
Thrown by any fs operation when the target path does not exist. Caused by path typos, wrong working directory, missing intermediate directories, or case-sensitivity mismatches on Linux.
View causes & fixes →
EMFILE: too many open files
Thrown when the process exceeds the OS per-process file descriptor limit. Common during bulk file operations, file watching with webpack or jest, or socket-heavy workloads. Fix with ulimit -n 65536, graceful-fs, or p-limit concurrency control.
View causes & fixes →
EACCES: permission denied
Thrown when the OS denies a file system or socket bind operation. Three common scenarios: app.listen(80) on Linux/macOS (privileged port), npm install -g against root-owned global node_modules, and fs operations on files the current user cannot access. Fix with reverse proxy, setcap, nvm, or chmod/chown. Never run Node.js as root.
View causes & fixes →
EPERM: operation not permitted
Predominantly a Windows error during npm install — VS Code or antivirus holds open file handles in node_modules while npm tries to rename them, or npm needs to create symlinks without SeCreateSymbolicLinkPrivilege. Fix by closing the IDE, adding antivirus exclusions, rimraf node_modules, npm cache clean --force, and enabling Windows Developer Mode for symlinks.
View causes & fixes →
ENOSPC: no space left on device
Same error code, two completely different causes: the Linux inotify watcher limit is exhausted by webpack/Vite/Jest/nodemon, or the disk is genuinely full during npm install or a CI build. Fix the watcher variant with fs.inotify.max_user_watches=524288; fix the disk variant with df -h, npm cache clean, and docker system prune.
View causes & fixes →

Network

EADDRINUSE: address already in use
Thrown when a server tries to listen() on a port already occupied by another process. Usually a leftover dev server or multiple running instances of the same app.
View causes & fixes →
ECONNRESET: connection reset by peer
Thrown when the remote server forcibly closes a TCP connection mid-transfer. Most often caused by a stale keep-alive socket or a load balancer idle timeout. Fix with retry logic and proper keepAliveTimeout settings.
View causes & fixes →
ECONNREFUSED: connection refused
Thrown as Error: connect ECONNREFUSED 127.0.0.1:PORT when nothing is listening on the target host and port. Caused by a service not running, wrong port, or Docker containers using localhost instead of the service name.
View causes & fixes →
ETIMEDOUT: connection timed out
Thrown when a TCP connect or read operation exceeds the timeout window with no response — the remote host went silent. Common causes: firewall silently dropping packets, overloaded server, or too-short default timeout. Fix with AbortSignal.timeout() and exponential backoff retry logic.
View causes & fixes →
ENOTFOUND: getaddrinfo ENOTFOUND
Thrown when DNS resolution fails — the hostname cannot be translated to an IP address. Also covers EAI_AGAIN (temporary DNS failure). Common causes: typo in hostname, wrong API_URL env var, using localhost inside Docker, or no internet connectivity.
View causes & fixes →
EPIPE: write EPIPE
Thrown as Error: write EPIPE when writing to a stream or socket whose reading end has been closed. Most common when piping output to head or grep, or writing to an HTTP response after the client disconnected. Fix with an error handler on process.stdout or use stream.pipeline().
View causes & fixes →
ERR_HTTP_HEADERS_SENT
Thrown as Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client when code attempts a second response after the first has flushed. Almost always caused by a missing return before res.send, double next() calls, or async callbacks firing after the response. Fix with return res.json(...) and the res.headersSent guard.
View causes & fixes →

Streams

ERR_STREAM_WRITE_AFTER_END
Thrown as Error [ERR_STREAM_WRITE_AFTER_END]: write after end when stream.write() or res.write() is called after stream.end(). Common with http-proxy after client disconnect, async callbacks landing after an early res.end(), and pipeline error handlers writing to a destroyed sink. Fix with writableEnded guards and stream.pipeline().
View causes & fixes →
ERR_STREAM_PREMATURE_CLOSE
Thrown as Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close when a stream in stream.pipeline() is destroyed before emitting end. Common with HTTP client disconnects mid-download, AbortController-aborted fetch bodies, and OpenAI/Anthropic LLM streams cancelled by the browser. Often expected — check err.code and treat as a client abort, not a server error.
View causes & fixes →

Runtime

TypeError: Cannot read properties of undefined
Thrown when a property is accessed on a value that is undefined. The most universal JavaScript error — fix with optional chaining (obj?.prop), null checks, or by ensuring async data has loaded.
View causes & fixes →
TypeError [ERR_INVALID_ARG_TYPE]
Thrown when a Node.js built-in receives an argument of the wrong type — almost always undefined instead of a string for path, data, or chunk arguments. Common causes: missing env var, missing await, or passing an unserialized object to response.end().
View causes & fixes →
ReferenceError: document is not defined
Thrown when browser-only globals like document, window, navigator, or localStorage are accessed in Node.js. Common in SSR frameworks (Next.js, Nuxt.js) and Jest tests. Fix with typeof guards, dynamic() with ssr: false, or testEnvironment: 'jsdom'.
View causes & fixes →
UnhandledPromiseRejection
Thrown when a Promise is rejected with no .catch() handler or try/catch around an await. Fatal since Node.js 15 — crashes the process with exit code 1. Common causes: missing await, forEach(async anti-pattern, and async Express route handlers without a wrapper.
View causes & fixes →
TypeError: Cannot set properties of undefined
The write-side complement to Cannot read properties of undefined. Thrown when assigning a property to an undefined value — uninitialized parent objects, nested paths, missing await, Map/Set confusion, or the optional-chaining write-side trap (obj?.x = v does not work). Fix with obj.a ??= {}, lodash set(), or Map.set().
View causes & fixes →
RangeError: Maximum call stack size exceeded
Thrown when V8's call stack runs out of frames (~10–15k). Causes: missing or wrong base case in recursion, JSON.stringify on an object with circular references, push.apply with a huge array, or mutual recursion. Fix with a correct base case, trampoline pattern, iterative stack, or WeakSet replacer for circular JSON. --stack-size only buys headroom — not a real fix.
View causes & fixes →

Memory

FATAL ERROR: JavaScript heap out of memory
A fatal V8 crash — not a catchable JavaScript error — that occurs when the Node.js process exhausts its heap. The default limit is ~1.5 GB. Triggered by loading large JSON/CSV files entirely into memory, memory leaks, or build tools on large codebases. Fix with --max-old-space-size=4096, streaming, batch processing, or worker_threads.
View causes & fixes →