![Create React App Officially Deprecated Amid React 19 Compatibility Issues](https://cdn.sanity.io/images/cgdhsj6q/production/04fa08cf844d798abc0e1a6391c129363cc7e2ab-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Create React App Officially Deprecated Amid React 19 Compatibility Issues
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
modern-errors
Advanced tools
Handle errors like it's 2022 🔮
Error handling framework that is minimalist yet featureful.
Error
instance, missing
stack, etc.)Create custom error types.
// `error.js`
import modernErrors from 'modern-errors'
export const { InputError, AuthError, DatabaseError, errorHandler, parse } =
modernErrors(['InputError', 'AuthError', 'DatabaseError'])
Wrap the main function with the error handler.
import { errorHandler } from './error.js'
export const main = async function (filePath) {
try {
return await readContents(filePath)
} catch (error) {
throw errorHandler(error)
}
}
Throw/re-throw errors.
import { InputError } from './error.js'
const readContents = async function (filePath) {
try {
return await readFile(filePath)
} catch (cause) {
throw new InputError(`Could not read ${filePath}`, { cause })
}
}
npm install modern-errors
This package is an ES module and must be loaded using
an import
or import()
statement,
not require()
.
errorNames
string[]
options
object
Return value: object
Creates custom error types.
Type: CustomErrorType
Any error name passed as argument is returned as an error type.
Type: (anyException) => Error
Error handler that should wrap each main function.
Type: (errorObject) => Error
Convert an error plain object into an Error instance.
Type: string | URL
URL where users should report unknown errors.
Type: (error, parameters) => void
Called on any
new CustomErrorType('message', parameters)
. Can be
used to customize error parameters or set
error type properties. By default, any parameters
are set as error properties.
// error.js
import modernErrors from 'modern-errors'
export const { InputError, AuthError, DatabaseError, errorHandler, parse } =
modernErrors(['InputError', 'AuthError', 'DatabaseError'])
Each main function should be wrapped with the errorHandler()
.
import { errorHandler } from './error.js'
export const main = async function (filePath) {
try {
return await readContents(filePath)
} catch (error) {
// `errorHandler()` returns `error`, so `throw` must be used
throw errorHandler(error)
}
}
import { InputError } from './error.js'
const validateFilePath = function (filePath) {
if (filePath === '') {
throw new InputError('Missing file path.')
}
}
Invalid errors are normalized
by errorHandler()
. This includes errors that are not an
Error
instance
or that have
wrong/missing properties.
import { errorHandler } from './error.js'
export const main = function (filePath) {
try {
throw 'Missing file path.'
} catch (error) {
throw errorHandler(error) // Normalized to an `Error` instance
}
}
Errors are re-thrown using the
standard cause
parameter.
This allows wrapping the error message,
properties, or type.
import { InputError } from './error.js'
const readContents = async function (filePath) {
try {
return await readFile(filePath)
} catch (cause) {
throw new InputError(`Could not read ${filePath}`, { cause })
}
}
The errorHandler()
merges all error cause
into a
single error, including their
message
,
stack
,
name
,
AggregateError.errors
and any additional property. This ensures:
error.cause
does not need to be
traversedThe outer error message is appended.
try {
await readFile(filePath)
} catch (cause) {
throw new InputError(`Could not read ${filePath}`, { cause })
// InputError: File does not exist.
// Could not read /example/path
}
If the outer error message ends with :
, it is prepended instead.
throw new InputError(`Could not read ${filePath}:`, { cause })
// InputError: Could not read /example/path: File does not exist.
:
can optionally be followed a newline.
throw new InputError(`Could not read ${filePath}:\n`, { cause })
// InputError: Could not read /example/path:
// File does not exist.
Once errorHandler()
has been applied, the error type can be
checked by its name
. Libraries should document their possible error names, but
do not need to export
their error types.
if (error.name === 'InputError') {
// ...
} else if (error.name === 'UnknownError') {
// ...
}
When re-throwing errors, the outer error type overrides the inner one.
try {
throw new AuthError('Could not authenticate.')
} catch (cause) {
throw new InputError('Could not read the file.', { cause })
// Now an InputError
}
However, the inner error type is kept if the outer one is Error
or
AggregateError
.
try {
throw new AuthError('Could not authenticate.')
} catch (cause) {
throw new Error('Could not read the file.', { cause })
// Still an AuthError
}
All errors should use known types: the ones returned by
modernErrors()
. Errors with an unknown type
should be handled in try {} catch {}
and re-thrown with a
known type instead.
The errorHandler()
assigns the UnknownError
type to any
error with an unknown type.
const getUserId = function (user) {
return user.id
}
getUserId(null) // UnknownError: Cannot read properties of null (reading 'id')
If the bugsUrl
option is used,
modernErrors({ bugsUrl: 'https://github.com/my-name/my-project/issues' })
any unknown error will include the following message.
Please report this bug at: https://github.com/my-name/my-project/issues
Unless the onCreate()
option is defined, any parameter is set as
an error property.
const error = new InputError('Could not read the file.', { filePath: '/path' })
console.log(error.filePath) // '/path'
Pass an empty message
in order to set error properties without wrapping the
message
.
try {
await readFile(filePath)
} catch (cause) {
throw new Error('', { cause, filePath: '/path' })
}
The onCreate()
option can be used to validate and transform error
parameters
.
modernErrors({
onCreate(error, parameters) {
const { filePath } = parameters
if (typeof filePath !== 'string') {
throw new Error('filePath must be a string.')
}
const hasFilePath = filePath !== undefined
Object.assign(error, { filePath, hasFilePath })
},
})
const error = new InputError('Could not read the file.', {
filePath: '/path',
unknownParam: true,
})
console.log(error.filePath) // '/path'
console.log(error.hasFilePath) // true
console.log(error.unknownParam) // undefined
The onCreate()
option can trigger error type-specific logic.
modernErrors({
onCreate(error, parameters) {
onCreateError[error.name](error, parameters)
},
})
const onCreateError = {
InputError(error, parameters) {
// ...
},
AuthError(error, parameters) {
// ...
},
// ...
}
The onCreate()
option can be used to set properties on all
instances of a given error type.
modernErrors({
onCreate(error, parameters) {
Object.assign(error, parameters, ERROR_PROPS[error.name])
},
})
const ERROR_PROPS = {
InputError: { isUser: true },
AuthError: { isUser: true },
DatabaseError: { isUser: false },
}
const error = new InputError('Could not read the file.')
console.log(error.isUser) // true
CLI applications can assign a different exit code and log verbosity per error
type by using handle-cli-error
.
#!/usr/bin/env node
import handleCliError from 'handle-cli-error'
// `programmaticMain()` must use `modern-errors`'s `errorHandler`
import programmaticMain from './main.js'
const cliMain = function () {
try {
const cliFlags = getCliFlags()
programmaticMain(cliFlags)
} catch (error) {
// Print `error` then exit the process
handleCliError(error, {
types: {
InputError: { exitCode: 1, short: true },
DatabaseError: { exitCode: 2, short: true },
default: { exitCode: 3 },
},
})
}
}
cliMain()
error.toJSON()
converts errors to plain objects that are
serializable to JSON
(or YAML,
etc.). It is
automatically called
by JSON.stringify()
. All error properties
are kept,
including
cause
.
The error
must be from a known type. However, any other
error (including Error
, TypeError
, RangeError
, etc.) is also serializable
providing it has been either passed to errorHandler()
, or
wrapped as an error.cause
.
try {
await readFile(filePath)
} catch (cause) {
const error = new InputError('Could not read the file.', {
cause,
filePath: '/path',
})
const errorObject = error.toJSON()
// {
// name: 'InputError',
// message: 'Could not read the file',
// stack: '...',
// cause: { name: 'Error', ... },
// filePath: '/path'
// }
const errorString = JSON.stringify(error)
// '{"name":"InputError",...}'
}
parse(errorObject)
converts those error plain objects back to
identical error instances.
The original error type is generically preserved. However, it is converted to a
generic Error
if it is neither a native type (TypeError
, RangeError
, etc.)
nor a known type.
const newErrorObject = JSON.parse(errorString)
const newError = parse(newErrorObject)
// InputError: Could not read the file.
// filePath: '/path'
// [cause]: Error: ...
Objects and arrays containing custom errors can be deeply serialized to JSON.
They can then be deeply parsed back using
JSON.parse()
's reviver.
const error = new InputError('Could not read the file.')
const deepObject = [{}, { error }]
const jsonString = JSON.stringify(deepObject)
const newDeepObject = JSON.parse(jsonString, (key, value) => parse(value))
console.log(newDeepObject[1].error) // InputError: Could not read the file.
This framework brings together a collection of modules which can also be used individually:
create-error-types
: Create
multiple error typeserror-type
: Create one error typeerror-serializer
: Convert
errors to/from plain objectsnormalize-exception
:
Normalize exceptions/errorsmerge-error-cause
: Merge an
error with its cause
error-cause-polyfill
:
Polyfill error.cause
handle-cli-error
: 💣 Error
handler for CLI applications 💥log-process-errors
: Show
some ❤ to Node.js process errorsFor 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.
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!
FAQs
Handle errors in a simple, stable, consistent way
The npm package modern-errors receives a total of 1,938 weekly downloads. As such, modern-errors popularity was classified as popular.
We found that modern-errors demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.