Module Resolution
Error: Cannot find module
Thrown by
View causes & fixes →
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.
ERR_PACKAGE_PATH_NOT_EXPORTED
Thrown when importing a subpath (e.g.
View causes & fixes →
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.
ERR_REQUIRE_ESM
Thrown when
View causes & fixes →
require() is used to load a pure ES module package.
Increasingly common as popular packages like chalk, node-fetch,
and nanoid drop CommonJS support.
ERR_REQUIRE_ASYNC_MODULE
Thrown on Node.js 20.19+ / 22.12+ when
View causes & fixes →
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.
SyntaxError: Cannot use import statement outside a module
Thrown when
View causes & fixes →
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'.
ERR_UNSUPPORTED_DIR_IMPORT
Thrown when an ESM
View causes & fixes →
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.
ERR_DLOPEN_FAILED
Thrown when Node.js cannot load a native addon (
View causes & fixes →
.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.
ERR_UNKNOWN_FILE_EXTENSION
Thrown as
View causes & fixes →
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.
ERR_INVALID_PACKAGE_CONFIG
Thrown when Node.js reads a
View causes & fixes →
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.
File System
ENOENT: no such file or directory
Thrown by any
View causes & fixes →
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.
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
View causes & fixes →
ulimit -n 65536,
graceful-fs, or p-limit concurrency control.
EACCES: permission denied
Thrown when the OS denies a file system or socket bind operation. Three common scenarios:
View causes & fixes →
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.
EPERM: operation not permitted
Predominantly a Windows error during
View causes & fixes →
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.
ENOSPC: no space left on device
Same error code, two completely different causes: the Linux
View causes & fixes →
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.
Network
EADDRINUSE: address already in use
Thrown when a server tries to
View causes & fixes →
listen() on a port already occupied by
another process. Usually a leftover dev server or multiple running instances of
the same app.
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
View causes & fixes →
keepAliveTimeout settings.
ECONNREFUSED: connection refused
Thrown as
View causes & fixes →
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.
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
View causes & fixes →
AbortSignal.timeout() and exponential backoff retry logic.
ENOTFOUND: getaddrinfo ENOTFOUND
Thrown when DNS resolution fails — the hostname cannot be translated to an IP address.
Also covers
View causes & fixes →
EAI_AGAIN (temporary DNS failure). Common causes: typo in hostname,
wrong API_URL env var, using localhost inside Docker, or no
internet connectivity.
EPIPE: write EPIPE
Thrown as
View causes & fixes →
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().
ERR_HTTP_HEADERS_SENT
Thrown as
View causes & fixes →
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.
Streams
ERR_STREAM_WRITE_AFTER_END
Thrown as
View causes & fixes →
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().
ERR_STREAM_PREMATURE_CLOSE
Thrown as
View causes & fixes →
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.
Runtime
TypeError: Cannot read properties of undefined
Thrown when a property is accessed on a value that is
View causes & fixes →
undefined.
The most universal JavaScript error — fix with optional chaining (obj?.prop),
null checks, or by ensuring async data has loaded.
TypeError [ERR_INVALID_ARG_TYPE]
Thrown when a Node.js built-in receives an argument of the wrong type — almost always
View causes & fixes →
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().
ReferenceError: document is not defined
Thrown when browser-only globals like
View causes & fixes →
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'.
UnhandledPromiseRejection
Thrown when a
View causes & fixes →
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.
TypeError: Cannot set properties of undefined
The write-side complement to Cannot read properties of undefined. Thrown when
assigning a property to an
View causes & fixes →
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().
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,
View causes & fixes →
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.