nodejs/node
Errors and validators
Purpose
Centralize how Node throws errors and validates arguments. Every error thrown by core has a stable, documented code (e.g. ERR_INVALID_ARG_TYPE). Every public-API argument check goes through lib/internal/validators.js. This makes user-facing errors consistent and gives downstream code something stable to match on.
Directory layout
lib/internal/
errors.js // The error-class registry (codes, classes, messages)
validators.js // validate* helpers
src/
node_errors.{cc,h} // C++ side: throw-friendly helpers + JS-error codes
node_errors.cc // implementations + V8 message hooks
doc/api/
errors.md // canonical doc: lists every code with stabilityKey abstractions
| Type / file | Role |
|---|---|
errorCodes (lib/internal/errors.js) |
Map of ERR_xxx → class with .code/.name/.message. |
E(code, msgOrFn, baseClass) (lib/internal/errors.js) |
Helper used to register each error code. |
validateString(...), validateInteger(...), etc. (lib/internal/validators.js) |
Throw consistent ERR_INVALID_ARG_TYPE/ERR_OUT_OF_RANGE. |
THROW_ERR_* macros (src/node_errors.h) |
C++ helpers that throw the matching JS error. |
errors::TriggerUncaughtException (src/node_errors.cc) |
Funnel for uncaught exceptions; honours --abort-on-uncaught-exception. |
How errors are defined
Inside lib/internal/errors.js:
E(
'ERR_INVALID_ARG_TYPE',
(name, expected, actual) => {
// detailed message construction
},
TypeError
);
E(
'ERR_OUT_OF_RANGE',
(str, range, input, replaceDefaultBoolean = false) => {
/* ... */
},
RangeError
);
E('ERR_FS_FILE_TOO_LARGE', 'File size (%s) is greater than 2 GiB', RangeError);E(code, msg, base) creates a class extending base (Error/TypeError/RangeError/SyntaxError/URIError) with a frozen .code, a deterministic message format, and registers it on codes.
Use:
const {
codes: { ERR_INVALID_ARG_TYPE },
} = require('internal/errors');
throw new ERR_INVALID_ARG_TYPE('options.signal', 'AbortSignal', signal);The same machinery lets process.on('uncaughtException') and stack frames carry the code in error.code so tests and user code can match on it.
How validators are used
lib/internal/validators.js exports the canonical validators:
| Validator | Throws when |
|---|---|
validateString(value, name) |
value is not a string |
validateNumber(value, name, min, max) |
not a number, or out of inclusive range |
validateInteger(value, name, min, max) |
not a safe integer in range |
validateBoolean(value, name) |
not a boolean |
validateFunction(value, name) |
not callable |
validateObject(value, name, options) |
not a plain object (with options for null/array allowance) |
validateArray(value, name, minLength) |
not an array, or too short |
validateBuffer(buf, name) |
not a Buffer/typed-array |
validatePort(port, name) |
not a valid TCP/UDP port |
validateAbortSignal(signal, name) |
not an AbortSignal |
validateOneOf(value, name, choices) |
value not in choices |
validateInt32/validateUint32 etc. |
range/bit-width checks |
The convention: validate at the top of every public method; never validate inside hot loops or in private helpers that have already been validated.
C++ errors
src/node_errors.h provides macros mirroring the JS codes:
THROW_ERR_INVALID_ARG_TYPE(env, "expected string");
return THROW_ERR_OUT_OF_RANGE(env, "...");Each macro creates a JS error with the matching code so a JS-side try { ... } catch (e) { e.code === 'ERR_OUT_OF_RANGE' } keeps working when the throw happens from C++.
errors::TriggerUncaughtException is the central choke point for uncaught exceptions — if you want to break in a debugger when any exception escapes JS, set a breakpoint there.
Integration points
util.format/util.inspect— error messages are formatted using primordial-safe helpers; do not call.toString()on user objects directly.process.emitWarning— for non-fatal cases. Implementation:lib/internal/process/warning.js.AbortError— special-cased class forAbortSignalcancellation.SystemError— wraps libuv/syscall errors witherrno,syscall,path,dest. Created inlib/internal/errors.js#hideStackFrames(SystemError).
Entry points for modification
- New error code? Add an
E(...)entry inlib/internal/errors.js, document it indoc/api/errors.md, and write at least one test that assertserr.code. - Tightening or relaxing an existing message? Errors are part of the public API — message changes go through a deprecation cycle. The stability levels are documented next to each code in
doc/api/errors.md. - Adding a C++ error helper?
src/node_errors.hERRORS_WITH_CODEandPREDEFINED_ERROR_MESSAGESmacros are the registry; don't bypass them.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.