module-error
Create errors with code and cause properties. Simple and extensible.
Usage
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.
API
ModuleError(message, [options])
Constructor to create an error with the provided message string. Options:
code(string): if provided, define acodeproperty with this value.cause(Error): if provided, define acauseproperty with this value. Unlike the spec ofproposal-error-causethe 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 aexpectedproperty 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.expectedis true and no--verboseflag was provided. Otherwise print the full stack.transient: if truthy, define atransientproperty with valuetrue. This communicates to users that the operation that caused the error may be retried. See alsotransient-errorto mark existing errors as transient.
Install
With npm do:
npm install module-error