normalize-exception v4.0.0
Normalize:
- Exceptions that are not
Errorinstances - Error properties (
name,message,stack,constructor) that are missing, invalid, enumerable, readonly, non-writable, non-configurable, non-extensible, proxied or throwing error.causeanderror.errorsrecursively, when present
Hire me
Please reach out if you're looking for a Node.js API or CLI engineer (11 years of experience). Most recently I have been Netlify Build's and Netlify Plugins' technical lead for 2.5 years. I am available for full-time remote positions.
Example
import normalizeException from 'normalize-exception'
try {
throw 'message'
} catch (error) {
console.log(error) // 'message'
console.log(normalizeException(error)) // Error: message
console.log(normalizeException(error) instanceof Error) // true
}Install
npm install normalize-exceptionThis package works in both Node.js >=18.18.0 and browsers.
This is an ES module. It must be loaded using
an import or import() statement,
not require(). If TypeScript is used, it must be configured to
output ES modules,
not CommonJS.
API
normalizeException(error, options?)
error any\
options Options\
Return value: Error
normalizeException() never throws.
If error is an Error instance, it is returned. Any missing or invalid error
property is directly modified.
If it is not an Error instance, a new one is created and returned.
Options
Options are an optional object with the following properties.
shallow
Type: boolean\
Default: false
Unless true,
error.cause
and
error.errors
are normalized recursively, when present.
Features
Invalid type
Strings
try {
throw 'message'
} catch (error) {
console.log(error) // 'message'
console.log(normalizeException(error)) // Error: message
console.log(normalizeException(error) instanceof Error) // true
}Plain objects
try {
throw { name: 'TypeError', message: 'message' }
} catch (error) {
console.log(normalizeException(error)) // TypeError: message
}Others
try {
throw null
} catch (error) {
console.log(error.message) // Throws
console.log(normalizeException(error).message) // 'null'
}Missing properties
try {
const error = new TypeError('message')
error.name = undefined
throw error
} catch (error) {
console.log(error.name) // undefined
console.log(normalizeException(error).name) // 'TypeError'
}Mismatched constructor
try {
const error = new TypeError('message')
error.constructor = RangeError
throw error
} catch (error) {
console.log(error.constructor) // RangeError
console.log(normalizeException(error).constructor) // TypeError
}Missing stack
try {
const error = new Error('message')
error.stack = undefined
throw error
} catch (error) {
console.log(error.stack) // undefined
console.log(normalizeException(error).stack) // 'Error: message ...'
}Invalid properties
try {
const error = new Error('message')
error.message = true
throw error
} catch (error) {
console.log(typeof error.message) // 'boolean'
console.log(typeof normalizeException(error).message) // 'string'
}Enumerable properties
class ExampleError extends Error {
constructor(...args) {
super(...args)
// Common mistake: this makes `error.name` enumerable
this.name = 'ExampleError'
}
}
try {
throw new ExampleError('message')
} catch (error) {
console.log({ ...error }) // { name: 'ExampleError' }
console.log({ ...normalizeException(error) }) // {}
}Readonly properties
try {
const error = new Error('message')
Object.defineProperty(error, 'message', { get: () => 'message' })
throw error
} catch (error) {
error.message = 'other' // Throws
normalizeException(error).message = 'other' // Does not throw
}Non-writable properties
try {
const error = new Error('message')
Object.defineProperty(error, 'message', { value: '', writable: false })
throw error
} catch (error) {
error.message = 'other' // Throws
normalizeException(error).message = 'other' // Does not throw
}Non-configurable properties
try {
const error = new Error('message')
Object.defineProperty(error, 'message', { value: '', configurable: false })
throw error
} catch (error) {
delete error.message // Throws
delete normalizeException(error).message // Does not throw
}Non-extensible error
try {
const error = new Error('message')
Object.preventExtensions(error)
throw error
} catch (error) {
error.prop = true // Throws
normalizeException(error).prop = true // Does not throw
}Proxies
try {
throw new Proxy(new Error('message'), {})
} catch (error) {
const { toString } = Object.prototype
console.log(toString.call(error)) // '[object Object]'
console.log(toString.call(normalizeException(error))) // '[object Error]'
}Throwing properties
Proxies
try {
throw new Proxy(new Error('message'), {
get: () => {
throw new Error('example')
},
})
} catch (error) {
console.log(error.message) // Throws
console.log(normalizeException(error).message) // Does not throw
}Getters
try {
const error = new Error('message')
Object.defineProperty(error, 'message', {
get: () => {
throw new Error('example')
},
})
throw error
} catch (error) {
console.log(error.message) // Throws
console.log(normalizeException(error).message) // Does not throw
}Recursion
error.cause
try {
throw new Error('message', { cause: 'innerError' })
} catch (error) {
console.log(error.cause instanceof Error) // false
console.log(normalizeException(error).cause instanceof Error) // true
}error.errors
try {
throw new AggregateError(['innerError'], 'message')
} catch (error) {
console.log(error.errors[0] instanceof Error) // false
console.log(normalizeException(error).errors[0] instanceof Error) // true
}Related projects
modern-errors: Handle errors in a simple, stable, consistent wayerror-custom-class: Create one error classerror-class-utils: Utilities to properly create error classeserror-serializer: Convert errors to/from plain objectsmerge-error-cause: Merge an error with itscauseis-error-instance: Check if a value is anErrorinstanceset-error-class: Properly update an error's classset-error-message: Properly update an error's messagewrap-error-message: Properly wrap an error's messageset-error-props: Properly update an error's propertiesset-error-stack: Properly update an error's stackerror-cause-polyfill: Polyfillerror.causehandle-cli-error: 💣 Error handler for CLI applications 💥log-process-errors: Show some ❤ to Node.js process errorserror-http-response: Create HTTP error responseswinston-error-format: Log errors with Winston
Support
For any question, don't hesitate to submit an issue on GitHub.
Everyone is welcome regardless of personal background. We enforce a Code of conduct in order to promote a positive and inclusive environment.
Contributing
This project was made with ❤️. The simplest way to give back is by starring and sharing it online.
If the documentation is unclear or has a typo, please click on the page's Edit
button (pencil icon) and suggest a correction.
If you would like to help us fix a bug or add a new feature, please check our guidelines. Pull requests are welcome!
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago