Create errors with code
and cause
properties. Simple and extensible.
Works like a regular Error
constructor but adds an options argument (as proposal-error-cause
does).
const ModuleError = require('module-error')
throw new ModuleError('Message goes here', {
code: 'EXAMPLE_NOT_FOUND'
})
The primary purpose of ModuleError
is to define a code
property on the error object following Node.js conventions. It should be set to an uppercase string that uniquely identifies a situation, prefixed with the name of your module (or a collection of modules) to prevent conflicts.
The output looks like this in Node.js (some stack frames omitted for brevity):
ModuleError: Message goes here
at Object.<anonymous> (/home/app/example.js:5:7)
at node:internal/main/run_main_module:17:47 {
code: 'EXAMPLE_NOT_FOUND'
}
The benefit of error codes is that messages can be changed without a semver-major release because your semver contract will be on the codes. Codes can be reused across related modules while allowing individual modules to customize messages. I also prefer it over instanceof MyError
logic because codes work cross-realm and when a tree of node_modules
contains multiple versions of a module.
To wrap another error:
try {
JSON.parse(await fs.readFile('state.json'))
} catch (err) {
throw new ModuleError('Could not load state', {
code: 'EXAMPLE_INVALID_STATE',
cause: err
})
}
If for convenience you want to create subclasses with prepared codes:
class NotFoundError extends ModuleError {
constructor(message, options) {
super(message, { ...options, code: 'EXAMPLE_NOT_FOUND' })
}
}
Then you can do:
throw new NotFoundError('Message goes here')
Under Node.js the stack trace will be adjusted accordingly, to skip the frame containing your error constructor.
Constructor to create an error with the provided message
string. Options:
code
(string): if provided, define acode
property with this value.cause
(Error): if provided, define acause
property with this value. Unlike the spec ofproposal-error-cause
the property is enumerable so that Node.js (v16 at the time of writing) will print it. Firefox prints it regardless, Chromium doesn't yet.expected
: if truthy, define aexpected
property with valuetrue
. This is useful for command line interfaces to differentiate unexpected errors from e.g. invalid user input. A pattern I like to follow is to print only an error message iferr.expected
is true and no--verbose
flag was provided. Otherwise print the full stack.transient
: if truthy, define atransient
property with valuetrue
. This communicates to users that the operation that caused the error may be retried. See alsotransient-error
to mark existing errors as transient.
With npm do:
npm install module-error