Error Codes

Node Error Codes and System Errors

When a call into the operating system fails — opening a file, binding a port, resolving a name — libuv hands back a system error: an ordinary Error with extra properties. code is the stable string identifier, errno the negative platform number, syscall the failed operation, plus whichever of path, address, port and hostname applies.

Reading the properties of a system errorJavaScript
import { readFile } from 'node:fs/promises';
import { getSystemErrorName, getSystemErrorMessage } from 'node:util';
try {
  await readFile('./config/app.json');
} catch (err) {
  console.log(err.code, err.errno, err.syscall, err.path);
  console.log(getSystemErrorName(err.errno), '-', getSystemErrorMessage(err.errno));
}
Output
ENOENT -4058 open C:\dev\shop\config\app.json
ENOENT - no such file or directory

util.getSystemErrorName() and util.getSystemErrorMessage() (both stable) turn a raw errno back into something readable. Note that errno above: on Unix libuv uses the negated C errno, so the same missing file reports -2 on Linux and macOS, while Windows uses arbitrary libuv numbers. Branch on code, never on errno, and never on message, which the Node documentation reserves the right to reword between releases.

System error codes you will meet most often in a MERN backend
Code Source Usual meaning
ENOENT fs, child_process Path or binary not found
EACCES / EPERM fs, net No permission; port below 1024
EADDRINUSE / ECONNREFUSED net, http Port held; nothing listening
ECONNRESET / EPIPE sockets Peer closed mid-transfer
ENOTFOUND dns, fetch Hostname did not resolve

Node's own JavaScript-level errors use the same field with a different naming scheme: uppercase and prefixed with ERR_ — ERR_INVALID_ARG_TYPE, ERR_MODULE_NOT_FOUND, ERR_UNHANDLED_REJECTION. Treat both families as one vocabulary and turn the common ones into advice: answering EADDRINUSE with ` console.error(Port ${err.port} is busy) and process.exit(1) costs three lines and saves the next developer a stack trace from node:net`.