Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
M

modern-errors

> 编程语言
Open source

Handle errors in a simple, stable, consistent way

1.5K stars0 likes1 views
WebsiteGitHub

About

Handle errors in a simple, stable, consistent way

Handle errors in a simple, stable, consistent way.

Features

Simple patterns to:

  • ⛑️ Create error classes
  • ️ Set error properties
  • Wrap or aggregate errors
  • Separate known and unknown errors

Stability:

  • Normalize invalid errors
  • ️ 100% test coverage
  • Strict TypeScript types

Plugins

  • modern-errors-cli: Handle errors in CLI modules
  • modern-errors-beautiful: Prettify error messages and stacks
  • modern-errors-process: Handle process errors
  • modern-errors-bugs: Print where to report bugs
  • modern-errors-serialize: Serialize/parse errors
  • modern-errors-clean: Clean stack traces
  • modern-errors-http: Create HTTP error responses
  • modern-errors-winston: Log errors with Winston
  • modern-errors-switch: Execute class-specific logic
  • Create your own plugin

Example

Create error classes.

javascript
import ModernError from 'modern-errors'

export const BaseError = ModernError.subclass('BaseError')

export const UnknownError = BaseError.subclass('UnknownError')
export const InputError = BaseError.subclass('InputError')
export const AuthError = BaseError.subclass('AuthError')
export const DatabaseError = BaseError.subclass('DatabaseError')

Set error properties.

javascript
throw new InputError('Invalid file path', { props: { filePath: '/...' } })

Wrap errors.

javascript
try {
  // ...
} catch (cause) {
  throw new InputError('Could not read the file.', { cause })
}

Normalize errors.

javascript
try {
  throw 'Missing file path.'
} catch (error) {
  // Normalized from a string to a `BaseError` instance
  throw BaseError.normalize(error)
}

Use plugins.

javascript
import ModernError from 'modern-errors'
import modernErrorsSerialize from 'modern-errors-serialize'

export const BaseError = ModernError.subclass('BaseError', {
  plugins: [modernErrorsSerialize],
})

// ...

// Serialize error as JSON, then back to identical error instance
const error = new InputError('Missing file path.')
const errorString = JSON.stringify(error)
const identicalError = BaseError.parse(JSON.parse(errorString))

Install

bash
npm install modern-errors

If any plugin is used, it must also be installed.

bash
npm install modern-errors-{pluginName}

This 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.

Usage

⛑️ Error classes

Create error classes

javascript
import ModernError from 'modern-errors'

export const BaseError = ModernError.subclass('BaseError')

export const UnknownError = BaseError.subclass('UnknownError')
export const InputError = BaseError.subclass('InputError')
export const AuthError = BaseError.subclass('AuthError')
export const DatabaseError = BaseError.subclass('DatabaseError')

Export error classes

Exporting and documenting all error classes allows consumers to check them. This also enables sharing error classes between modules.

Check error classes

javascript
if (error instanceof InputError) {
  // ...
}

Error subclasses

ErrorClass.subclass() returns a subclass. Parent classes' options are merged with their subclasses.

javascript
export const BaseError = ModernError.subclass('BaseError', {
  props: { isError: true },
})
export const InputError = BaseError.subclass('InputError', {
  props: { isUserError: true },
})

const error = new InputError('...')
console.log(error.isError) // true
console.log(error.isUserError) // true
console.log(error instanceof BaseError) // true
console.log(error instanceof InputError) // true

️ Error properties

Error class properties

javascript
const InputError = BaseError.subclass('InputError', {
  props: { isUserError: true },
})
const error = new InputError('...')
console.log(error.isUserError) // true

Error instance properties

javascript
const error = new InputError('...', { props: { isUserError: true } })
console.log(error.isUserError) // true

Internal error properties

Error properties that are internal or secret can be prefixed with _. This makes them non-enumerable, which prevents iterating or logging them.

javascript
const error = new InputError('...', {
  props: { userId: 6, _isUserError: true },
})
console.log(error.userId) // 6
console.log(error._isUserError) // true
console.log(Object.keys(error)) // ['userId']
console.log(error) // `userId` is logged, but not `_isUserError`

Wrap errors

Throw errors

javascript
throw new InputError('Missing file path.')

Wrap inner error

Any error's message, class and options can be wrapped using the standard cause option.

Instead of being set as a cause property, the inner error is directly merged to the outer error, including its message, stack, name, AggregateError.errors and any additional property.

javascript
try {
  // ...
} catch (cause) {
  throw new InputError('Could not read the file.', { cause })
}

Wrap error message

The outer error message is appended, unless it is empty. If the outer error message ends with : or :\n, it is prepended instead.

javascript
const cause = new InputError('File does not exist.')
// InputError: File does not exist.
throw new InputError('', { cause })
javascript
// InputError: File does not exist.
// Could not read the file.
throw new InputError('Could not read the file.', { cause })
javascript
// InputError: Could not read the file: File does not exist.
throw new InputError(`Could not read the file:`, { cause })
javascript
// InputError: Could not read the file:
// File does not exist.
throw new InputError(`Could not read the file:\n`, { cause })

Wrap error class

The outer error's class replaces the inner one.

javascript
try {
  throw new AuthError('...')
} catch (cause) {
  // Now an InputError
  throw new InputError('...', { cause })
}

Except when the outer error's class is a parent class, such as BaseError.

javascript
try {
  throw new AuthError('...')
} catch (cause) {
  // Still an AuthError
  throw new BaseError('...', { cause })
}

Wrap error options

The outer error's props and plugin options are merged.

javascript
try {
  throw new AuthError('...', innerOptions)
} catch (cause) {
  // `outerOptions` are merged with `innerOptions`
  throw new BaseError('...', { ...outerOptions, cause })
}

Aggregate errors

The errors option aggregates multiple errors into one. This is like new AggregateError(errors) except that it works with any error class.

javascript
const databaseError = new DatabaseError('...')
const authError = new AuthError('...')
throw new InputError('...', { errors: [databaseError, authError] })
// InputError: ... {
//   [errors]: [
//     DatabaseError: ...
//     AuthError: ...
//   ]
// }

Normalize errors

Wrapped errors

Any error can be directly passed to the cause or errors option, even if it is invalid, unknown or not normalized.

javascript
try {
  // ...
} catch (cause) {
  throw new InputError('...', { cause })
}

Invalid errors

Manipulating errors that are not Error instances or that have invalid properties can lead to unexpected bugs. BaseError.normalize() fixes that.

javascript
try {
  throw 'Missing file path.'
} catch (invalidError) {
  // This fails: `invalidError.message` is `undefined`
  console.log(invalidError.message.trim())
}
javascript
try {
  throw 'Missing file path.'
} catch (invalidError) {
  const normalizedError = BaseError.normalize(invalidError)
  // This works: 'Missing file path.'
  // `normalizedError` is a `BaseError` instance.
  console.log(normalizedError.message.trim())
}

Unknown errors

Handling known errors

Known errors should be handled in a try {} catch {} block and wrapped with a specific class. That block should only cover the statement that might throw in order to prevent catching other unrelated errors.

javascript
try {
  return regExp.test(value)
} catch (error) {
  // Now an `InputError` instance
  throw new InputError('Invalid regular expression:', { cause: error })
}

Normalizing unknown errors

If an error is not handled as described above, it is considered unknown. This indicates an unexpected exception, usually a bug. BaseError.normalize(error, UnknownError) assigns the UnknownError class to those errors.

javascript
export const UnknownError = BaseError.subclass('UnknownError')
javascript
try {
  return regExp.test(value)
} catch (error) {
  // Now an `UnknownError` instance
  throw BaseError.normalize(error, UnknownError)
}

Top-level error handler

Wrapping a module's main functions with BaseError.normalize(error, UnknownError) ensures every error being thrown is valid, applies plugins, and has a class that is either known or UnknownError.

javascript
export const main = () => {
  try {
    // ...
  } catch (error) {
    throw BaseError.normalize(error, UnknownError)
  }
}

Plugins

List of plugins

Plugins extend modern-errors features. All available plugins are listed here.

Adding plugins

To use a plugin, please install it, then pass it to the [plugins optio

Issues· 1 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

JavaScriptbrowsercausecode-qualityerror

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言