![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.)The framework integrates with other libraries to also:
Create the error types and handler.
// `error.js`
import modernErrors from 'modern-errors'
export const { errorHandler, InputError, AuthError, DatabaseError } =
modernErrors()
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()
.
options
object
Return value: object
Creates the error types and handler.
Type: ErrorType
Any error type can be retrieved from the
return value. The name must end with Error
. For example: InputError
,
AuthError
, etc.
Type: (anyException) => Error
Error handler that should wrap each main function.
Type: string | URL
URL where users should report internal errors/bugs.
Type: (error, parameters) => void
Called on any new ErrorType('message', parameters)
.
Can be used to customize error parameters or set
error type properties. By default, any parameters
are set as error properties.
✨ Retrieving the error types automatically creates them. ✨
// error.js
import modernErrors from 'modern-errors'
// The error types are examples: any name ending with "Error" can be specified
export const { errorHandler, InputError, AuthError, DatabaseError } =
modernErrors()
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 === 'InternalError') {
// ...
}
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
}
Internal errors/bugs can be distinguished from user errors by
handling any possible errors in try {} catch {}
and
re-throwing them
with a specific error type. The
errorHandler()
assigns the InternalError
type to any error
with an unknown type.
const getUserId = function (user) {
return user.id
}
getUserId(null) // InternalError: Cannot read properties of null (reading 'id')
If the bugsUrl
option is used,
modernErrors({ bugsUrl: 'https://github.com/my-name/my-project/issues' })
any internal 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) {
// ...
},
// ...
}
By default, error types are very similar except for their
name
.
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, {
InputError: { exitCode: 1, short: true },
DatabaseError: { exitCode: 2, short: true },
default: { exitCode: 3 },
})
}
}
cliMain()
When using a build step (Babel, TypeScript, etc.), the error stack traces refer to the built files/lines instead of the source. This can be fixed by using source maps:
--enable-source-maps
CLI flagnode-source-map-support
stacktrace.js
error-type
: Create custom error
typesnormalize-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 applicationsFor 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!
1.3.0
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.