{"id":13468228,"url":"https://github.com/ehmicky/modern-errors","last_synced_at":"2025-05-13T23:06:44.641Z","repository":{"id":37237256,"uuid":"502105368","full_name":"ehmicky/modern-errors","owner":"ehmicky","description":"Handle errors in a simple, stable, consistent way","archived":false,"fork":false,"pushed_at":"2025-03-29T03:36:21.000Z","size":9788,"stargazers_count":1472,"open_issues_count":1,"forks_count":18,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-04-03T11:38:10.928Z","etag":null,"topics":["browser","cause","code-quality","error","error-classes","error-handler","error-handling","error-monitoring","error-reporting","errors","exceptions","framework","javascript","library","message","monitoring","nodejs","plugins","stacktrace","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ehmicky.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-10T16:10:06.000Z","updated_at":"2025-04-02T22:30:55.000Z","dependencies_parsed_at":"2024-04-22T20:37:04.268Z","dependency_job_id":"a4f5d5fc-0ce2-419b-8f64-ae175604692b","html_url":"https://github.com/ehmicky/modern-errors","commit_stats":{"total_commits":2542,"total_committers":4,"mean_commits":635.5,"dds":0.008261211644374544,"last_synced_commit":"a04348d40c6f8ec07e1bec67c1689909b4873409"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmicky%2Fmodern-errors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmicky%2Fmodern-errors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmicky%2Fmodern-errors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmicky%2Fmodern-errors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ehmicky","download_url":"https://codeload.github.com/ehmicky/modern-errors/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248252661,"owners_count":21072699,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","cause","code-quality","error","error-classes","error-handler","error-handling","error-monitoring","error-reporting","errors","exceptions","framework","javascript","library","message","monitoring","nodejs","plugins","stacktrace","typescript"],"created_at":"2024-07-31T15:01:07.326Z","updated_at":"2025-04-10T16:20:40.535Z","avatar_url":"https://github.com/ehmicky.png","language":"JavaScript","readme":"\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/ehmicky/design/main/modern-errors/modern-errors_dark.svg\"/\u003e\n  \u003cimg alt=\"modern-errors logo\" src=\"https://raw.githubusercontent.com/ehmicky/design/main/modern-errors/modern-errors.svg\" width=\"600\"/\u003e\n\u003c/picture\u003e\n\n[![Node](https://img.shields.io/badge/-Node.js-808080?logo=node.js\u0026colorA=404040\u0026logoColor=66cc33)](https://www.npmjs.com/package/modern-errors)\n[![Browsers](https://img.shields.io/badge/-Browsers-808080?logo=firefox\u0026colorA=404040)](https://unpkg.com/modern-errors?module)\n[![TypeScript](https://img.shields.io/badge/-Typed-808080?logo=typescript\u0026colorA=404040\u0026logoColor=0096ff)](/src/main.d.ts)\n[![Codecov](https://img.shields.io/badge/-Tested%20100%25-808080?logo=codecov\u0026colorA=404040)](https://codecov.io/gh/ehmicky/modern-errors)\n[![Minified size](https://img.shields.io/bundlephobia/minzip/modern-errors?label\u0026colorA=404040\u0026colorB=808080\u0026logo=webpack)](https://bundlephobia.com/package/modern-errors)\n[![Mastodon](https://img.shields.io/badge/-Mastodon-808080.svg?logo=mastodon\u0026colorA=404040\u0026logoColor=9590F9)](https://fosstodon.org/@ehmicky)\n[![Medium](https://img.shields.io/badge/-Medium-808080.svg?logo=medium\u0026colorA=404040)](https://medium.com/@ehmicky)\n\nHandle errors in a simple, stable, consistent way.\n\n# Features\n\nSimple patterns to:\n\n- ⛑️ Create error [classes](#create-error-classes)\n- 🏷️ Set error [properties](#%EF%B8%8F-error-properties)\n- 🎀 [Wrap](#-wrap-errors) or [aggregate](#aggregate-errors) errors\n- 🐞 Separate known and [unknown](#-unknown-errors) errors\n\nStability:\n\n- 🚨 [Normalize](#-normalize-errors) invalid errors\n- 🛡️ 100% [test coverage](https://app.codecov.io/gh/ehmicky/modern-errors)\n- 🤓 Strict [TypeScript types](docs/typescript.md)\n\n# Plugins\n\n- [`modern-errors-cli`](https://github.com/ehmicky/modern-errors-cli): Handle\n  errors in CLI modules\n- [`modern-errors-process`](https://github.com/ehmicky/modern-errors-process):\n  Handle process errors\n- [`modern-errors-bugs`](https://github.com/ehmicky/modern-errors-bugs): Print\n  where to report bugs\n- [`modern-errors-serialize`](https://github.com/ehmicky/modern-errors-serialize):\n  Serialize/parse errors\n- [`modern-errors-clean`](https://github.com/ehmicky/modern-errors-clean): Clean\n  stack traces\n- [`modern-errors-http`](https://github.com/ehmicky/modern-errors-http): Create\n  HTTP error responses\n- [`modern-errors-winston`](https://github.com/ehmicky/modern-errors-winston):\n  Log errors with Winston\n- [`modern-errors-switch`](https://github.com/ehmicky/modern-errors-switch):\n  Execute class-specific logic\n- 🔌 Create your [own plugin](docs/plugins.md)\n\n# Example\n\nCreate error [classes](#%EF%B8%8F-error-classes).\n\n```js\nimport ModernError from 'modern-errors'\n\nexport const BaseError = ModernError.subclass('BaseError')\n\nexport const UnknownError = BaseError.subclass('UnknownError')\nexport const InputError = BaseError.subclass('InputError')\nexport const AuthError = BaseError.subclass('AuthError')\nexport const DatabaseError = BaseError.subclass('DatabaseError')\n```\n\nSet error [properties](#%EF%B8%8F-error-properties).\n\n```js\nthrow new InputError('Invalid file path', { props: { filePath: '/...' } })\n```\n\n[Wrap](#-wrap-errors) errors.\n\n```js\ntry {\n  // ...\n} catch (cause) {\n  throw new InputError('Could not read the file.', { cause })\n}\n```\n\n[Normalize](#-normalize-errors) errors.\n\n\u003c!-- eslint-disable no-throw-literal --\u003e\n\n```js\ntry {\n  throw 'Missing file path.'\n} catch (error) {\n  // Normalized from a string to a `BaseError` instance\n  throw BaseError.normalize(error)\n}\n```\n\nUse [plugins](#-plugins).\n\n```js\nimport ModernError from 'modern-errors'\nimport modernErrorsSerialize from 'modern-errors-serialize'\n\nexport const BaseError = ModernError.subclass('BaseError', {\n  plugins: [modernErrorsSerialize],\n})\n\n// ...\n\n// Serialize error as JSON, then back to identical error instance\nconst error = new InputError('Missing file path.')\nconst errorString = JSON.stringify(error)\nconst identicalError = BaseError.parse(JSON.parse(errorString))\n```\n\n# Install\n\n```bash\nnpm install modern-errors\n```\n\nIf any [plugin](#-plugins) is used, it must also be installed.\n\n```bash\nnpm install modern-errors-{pluginName}\n```\n\nThis package works in both Node.js \u003e=18.18.0 and\n[browsers](https://raw.githubusercontent.com/ehmicky/dev-tasks/main/src/browserslist).\n\nThis is an ES module. It must be loaded using\n[an `import` or `import()` statement](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c),\nnot `require()`. If TypeScript is used, it must be configured to\n[output ES modules](https://www.typescriptlang.org/docs/handbook/esm-node.html),\nnot CommonJS.\n\n# Usage\n\n## ⛑️ Error classes\n\n### Create error classes\n\n```js\nimport ModernError from 'modern-errors'\n\nexport const BaseError = ModernError.subclass('BaseError')\n\nexport const UnknownError = BaseError.subclass('UnknownError')\nexport const InputError = BaseError.subclass('InputError')\nexport const AuthError = BaseError.subclass('AuthError')\nexport const DatabaseError = BaseError.subclass('DatabaseError')\n```\n\n### Export error classes\n\nExporting and documenting all error classes allows consumers to check them. This\nalso enables sharing error classes between modules.\n\n### Check error classes\n\n```js\nif (error instanceof InputError) {\n  // ...\n}\n```\n\n### Error subclasses\n\n[`ErrorClass.subclass()`](#errorclasssubclassname-options) returns a\n[subclass](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends).\nParent classes' [options](#options) are merged with their subclasses.\n\n```js\nexport const BaseError = ModernError.subclass('BaseError', {\n  props: { isError: true },\n})\nexport const InputError = BaseError.subclass('InputError', {\n  props: { isUserError: true },\n})\n\nconst error = new InputError('...')\nconsole.log(error.isError) // true\nconsole.log(error.isUserError) // true\nconsole.log(error instanceof BaseError) // true\nconsole.log(error instanceof InputError) // true\n```\n\n## 🏷️ Error properties\n\n### Error class properties\n\n```js\nconst InputError = BaseError.subclass('InputError', {\n  props: { isUserError: true },\n})\nconst error = new InputError('...')\nconsole.log(error.isUserError) // true\n```\n\n### Error instance properties\n\n```js\nconst error = new InputError('...', { props: { isUserError: true } })\nconsole.log(error.isUserError) // true\n```\n\n### Internal error properties\n\nError properties that are internal or secret can be prefixed with `_`. This\nmakes them\n[non-enumerable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties),\nwhich prevents iterating or logging them.\n\n\u003c!-- eslint-disable no-underscore-dangle --\u003e\n\n```js\nconst error = new InputError('...', {\n  props: { userId: 6, _isUserError: true },\n})\nconsole.log(error.userId) // 6\nconsole.log(error._isUserError) // true\nconsole.log(Object.keys(error)) // ['userId']\nconsole.log(error) // `userId` is logged, but not `_isUserError`\n```\n\n## 🎀 Wrap errors\n\n### Throw errors\n\n```js\nthrow new InputError('Missing file path.')\n```\n\n### Wrap inner error\n\nAny error's [message](#wrap-error-message), [class](#wrap-error-class) and\n[options](#wrap-error-options) can be wrapped using the\n[standard](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause)\n[`cause` option](#optionscause).\n\nInstead of being set as a `cause` property, the inner error is directly\n[merged](https://github.com/ehmicky/merge-error-cause) to the outer error,\nincluding its\n[`message`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/message),\n[`stack`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/stack),\n[`name`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/name),\n[`AggregateError.errors`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError)\nand any [additional property](#%EF%B8%8F-error-properties).\n\n```js\ntry {\n  // ...\n} catch (cause) {\n  throw new InputError('Could not read the file.', { cause })\n}\n```\n\n### Wrap error message\n\nThe outer error message is appended, unless it is empty. If the outer error\nmessage ends with `:` or `:\\n`, it is prepended instead.\n\n```js\nconst cause = new InputError('File does not exist.')\n// InputError: File does not exist.\nthrow new InputError('', { cause })\n```\n\n```js\n// InputError: File does not exist.\n// Could not read the file.\nthrow new InputError('Could not read the file.', { cause })\n```\n\n```js\n// InputError: Could not read the file: File does not exist.\nthrow new InputError(`Could not read the file:`, { cause })\n```\n\n```js\n// InputError: Could not read the file:\n// File does not exist.\nthrow new InputError(`Could not read the file:\\n`, { cause })\n```\n\n### Wrap error class\n\nThe outer error's class replaces the inner one.\n\n```js\ntry {\n  throw new AuthError('...')\n} catch (cause) {\n  // Now an InputError\n  throw new InputError('...', { cause })\n}\n```\n\nExcept when the outer error's class is a parent class, such as\n[`BaseError`](#create-error-classes).\n\n```js\ntry {\n  throw new AuthError('...')\n} catch (cause) {\n  // Still an AuthError\n  throw new BaseError('...', { cause })\n}\n```\n\n### Wrap error options\n\nThe outer error's [`props`](#%EF%B8%8F-error-properties) and\n[plugin options](#plugin-options) are merged.\n\n```js\ntry {\n  throw new AuthError('...', innerOptions)\n} catch (cause) {\n  // `outerOptions` are merged with `innerOptions`\n  throw new BaseError('...', { ...outerOptions, cause })\n}\n```\n\n### Aggregate errors\n\nThe [`errors` option](#optionserrors) aggregates multiple errors into one. This\nis like\n[`new AggregateError(errors)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError/AggregateError)\nexcept that it works with any error class.\n\n```js\nconst databaseError = new DatabaseError('...')\nconst authError = new AuthError('...')\nthrow new InputError('...', { errors: [databaseError, authError] })\n// InputError: ... {\n//   [errors]: [\n//     DatabaseError: ...\n//     AuthError: ...\n//   ]\n// }\n```\n\n## 🚨 Normalize errors\n\n### Wrapped errors\n\nAny error can be directly passed to the [`cause`](#wrap-inner-error) or\n[`errors`](#aggregate-errors) option, even if it is [invalid](#invalid-errors),\n[unknown](#-unknown-errors) or not\n[normalized](#errorclassnormalizeerror-newerrorclass).\n\n```js\ntry {\n  // ...\n} catch (cause) {\n  throw new InputError('...', { cause })\n}\n```\n\n### Invalid errors\n\nManipulating errors that are not\n[`Error` instances](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)\nor that have\n[invalid properties](https://github.com/ehmicky/normalize-exception#features)\ncan lead to unexpected bugs.\n[`BaseError.normalize()`](#errorclassnormalizeerror-newerrorclass) fixes that.\n\n\u003c!-- eslint-disable no-throw-literal --\u003e\n\n```js\ntry {\n  throw 'Missing file path.'\n} catch (invalidError) {\n  // This fails: `invalidError.message` is `undefined`\n  console.log(invalidError.message.trim())\n}\n```\n\n\u003c!-- eslint-disable no-throw-literal --\u003e\n\n```js\ntry {\n  throw 'Missing file path.'\n} catch (invalidError) {\n  const normalizedError = BaseError.normalize(invalidError)\n  // This works: 'Missing file path.'\n  // `normalizedError` is a `BaseError` instance.\n  console.log(normalizedError.message.trim())\n}\n```\n\n## 🐞 Unknown errors\n\n### Handling known errors\n\nKnown errors should be handled in a `try {} catch {}` block and\n[wrapped](#wrap-error-class) with a [specific class](#create-error-classes).\nThat block should only cover the statement that might throw in order to prevent\ncatching other unrelated errors.\n\n\u003c!-- eslint-skip --\u003e\n\n```js\ntry {\n  return regExp.test(value)\n} catch (error) {\n  // Now an `InputError` instance\n  throw new InputError('Invalid regular expression:', { cause: error })\n}\n```\n\n### Normalizing unknown errors\n\nIf an error is not handled as described [above](#handling-known-errors), it is\nconsidered _unknown_. This indicates an unexpected exception, usually a bug.\n[`BaseError.normalize(error, UnknownError)`](#errorclassnormalizeerror-newerrorclass)\nassigns the `UnknownError` class to those errors.\n\n```js\nexport const UnknownError = BaseError.subclass('UnknownError')\n```\n\n\u003c!-- eslint-skip --\u003e\n\n```js\ntry {\n  return regExp.test(value)\n} catch (error) {\n  // Now an `UnknownError` instance\n  throw BaseError.normalize(error, UnknownError)\n}\n```\n\n### Top-level error handler\n\nWrapping a module's main functions with\n[`BaseError.normalize(error, UnknownError)`](#errorclassnormalizeerror-newerrorclass)\nensures every error being thrown is [valid](#invalid-errors), applies\n[plugins](#-plugins), and has a class that is either\n[_known_](#create-error-classes) or [`UnknownError`](#-unknown-errors).\n\n```js\nexport const main = () =\u003e {\n  try {\n    // ...\n  } catch (error) {\n    throw BaseError.normalize(error, UnknownError)\n  }\n}\n```\n\n## 🔌 Plugins\n\n### List of plugins\n\nPlugins extend `modern-errors` features. All available plugins are\n[listed here](#plugins).\n\n### Adding plugins\n\nTo use a plugin, please install it, then pass it to the\n[`plugins` option](#optionsplugins).\n\n```bash\nnpm install modern-errors-{pluginName}\n```\n\n\u003c!-- eslint-disable import/order --\u003e\n\n```js\nimport ModernError from 'modern-errors'\n\nimport modernErrorsBugs from 'modern-errors-bugs'\nimport modernErrorsSerialize from 'modern-errors-serialize'\n\nexport const BaseError = ModernError.subclass('BaseError', {\n  plugins: [modernErrorsBugs, modernErrorsSerialize],\n})\n// ...\n```\n\n### Custom plugins\n\nPlease see the [following documentation](docs/plugins.md) to create your own\nplugin.\n\n### Plugin options\n\nMost plugins can be configured with options. The option's name is the same as\nthe plugin.\n\n```js\nconst options = {\n  // `modern-errors-bugs` options\n  bugs: 'https://github.com/my-name/my-project/issues',\n  // `props` can be configured and modified like plugin options\n  props: { userId: 5 },\n}\n```\n\nPlugin options can apply to (in priority order):\n\n- Any error: second argument to [`ModernError.subclass()`](#options-1)\n\n```js\nexport const BaseError = ModernError.subclass('BaseError', options)\n```\n\n- Any error of a specific class (and its subclasses): second argument to\n  [`ErrorClass.subclass()`](#options-1)\n\n```js\nexport const InputError = BaseError.subclass('InputError', options)\n```\n\n- A specific error: second argument to [`new ErrorClass()`](#options-3)\n\n```js\nthrow new InputError('...', options)\n```\n\n- A plugin method call: last argument, passing only that plugin's options\n\n```js\nErrorClass[methodName](...args, options[pluginName])\n```\n\n```js\nerror[methodName](...args, options[pluginName])\n```\n\n## 🔧 Custom logic\n\nThe [`custom` option](#optionscustom) can be used to provide an error `class`\nwith additional methods, `constructor`, properties or options.\n\n\u003c!-- eslint-disable no-param-reassign, fp/no-mutation,\n     class-methods-use-this --\u003e\n\n```js\nexport const InputError = BaseError.subclass('InputError', {\n  // The `class` must extend from the parent error class\n  custom: class extends BaseError {\n    // If a `constructor` is defined, its parameters must be (message, options)\n    // Additional `options` can be defined.\n    constructor(message, options) {\n      message += options?.suffix ?? ''\n      super(message, options)\n    }\n\n    isUserInput() {\n      // ...\n    }\n  },\n})\n\nconst error = new InputError('Wrong user name', { suffix: ': example' })\nconsole.log(error.message) // 'Wrong user name: example'\nconsole.log(error.isUserInput())\n```\n\n## 🤓 TypeScript\n\nPlease see the [following documentation](docs/typescript.md) for information\nabout TypeScript types.\n\n# API\n\n## ModernError\n\nTop-level `ErrorClass`.\n\n## ErrorClass.subclass(name, options?)\n\n`name`: `string`\\\n`options`: [`ClassOptions?`](#options)\n\nCreates and returns a child `ErrorClass`.\n\n### options\n\n#### options.props\n\n_Type_: `object`\n\n[Error class properties](#error-class-properties).\n\n#### options.plugins\n\n_Type_: [`Plugin[]`](#-plugins)\n\n#### options.custom\n\n_Type_: `class extends ErrorClass {}`\n\n[Custom class](#-custom-logic) to add any methods, `constructor` or properties.\n\n#### options.\\*\n\nAny [plugin options](#plugin-options) can also be specified.\n\n## new ErrorClass(message, options?)\n\n`message`: `string`\\\n`options`: [`InstanceOptions?`](#options-2)\\\n_Return value_: `Error`\n\n### options\n\n#### options.props\n\n_Type_: `object`\n\n[Error instance properties](#error-instance-properties).\n\n#### options.cause\n\n_Type_: [`any`](#wrapped-errors)\n\nInner error being [wrapped](#-wrap-errors).\n\n#### options.errors\n\n_Type_: `any[]`\n\nArray of errors being [aggregated](#aggregate-errors).\n\n#### options.\\*\n\nAny [plugin options](#plugin-options) can also be specified.\n\n## ErrorClass.normalize(error, NewErrorClass?)\n\n`error`: `Error | any`\\\n`NewErrorClass`: subclass of `ErrorClass`\\\n_Return value_: `Error`\n\nNormalizes [invalid errors](#invalid-errors).\n\nIf the `error`'s class is a subclass of `ErrorClass`, it is left as is.\nOtherwise, it is [converted to `NewErrorClass`](#normalizing-unknown-errors),\nwhich defaults to `ErrorClass` itself.\n\n# Modules\n\nThis framework brings together a collection of modules which can also be used\nindividually:\n\n- [`error-custom-class`](https://github.com/ehmicky/error-custom-class): Create\n  one error class\n- [`error-class-utils`](https://github.com/ehmicky/error-class-utils): Utilities\n  to properly create error classes\n- [`error-serializer`](https://github.com/ehmicky/error-serializer): Convert\n  errors to/from plain objects\n- [`normalize-exception`](https://github.com/ehmicky/normalize-exception):\n  Normalize exceptions/errors\n- [`is-error-instance`](https://github.com/ehmicky/is-error-instance): Check if\n  a value is an `Error` instance\n- [`merge-error-cause`](https://github.com/ehmicky/merge-error-cause): Merge an\n  error with its `cause`\n- [`set-error-class`](https://github.com/ehmicky/set-error-class): Properly\n  update an error's class\n- [`set-error-message`](https://github.com/ehmicky/set-error-message): Properly\n  update an error's message\n- [`wrap-error-message`](https://github.com/ehmicky/wrap-error-message):\n  Properly wrap an error's message\n- [`set-error-props`](https://github.com/ehmicky/set-error-props): Properly\n  update an error's properties\n- [`set-error-stack`](https://github.com/ehmicky/set-error-stack): Properly\n  update an error's stack\n- [`handle-cli-error`](https://github.com/ehmicky/handle-cli-error): 💣 Error\n  handler for CLI applications 💥\n- [`log-process-errors`](https://github.com/ehmicky/log-process-errors): Show\n  some ❤ to Node.js process errors\n- [`error-http-response`](https://github.com/ehmicky/error-http-response):\n  Create HTTP error responses\n- [`winston-error-format`](https://github.com/ehmicky/winston-error-format): Log\n  errors with Winston\n\n# Support\n\nFor any question, _don't hesitate_ to [submit an issue on GitHub](../../issues).\n\nEveryone is welcome regardless of personal background. We enforce a\n[Code of conduct](CODE_OF_CONDUCT.md) in order to promote a positive and\ninclusive environment.\n\n# Contributing\n\nThis project was made with ❤️. The simplest way to give back is by starring and\nsharing it online.\n\nIf the documentation is unclear or has a typo, please click on the page's `Edit`\nbutton (pencil icon) and suggest a correction.\n\nIf you would like to help us fix a bug or add a new feature, please check our\n[guidelines](CONTRIBUTING.md). Pull requests are welcome!\n\n\u003c!-- Thanks go to our wonderful contributors: --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://fosstodon.org/@ehmicky\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/8136211?v=4?s=100\" width=\"100px;\" alt=\"ehmicky\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eehmicky\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/ehmicky/modern-errors/commits?author=ehmicky\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#design-ehmicky\" title=\"Design\"\u003e🎨\u003c/a\u003e \u003ca href=\"#ideas-ehmicky\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"https://github.com/ehmicky/modern-errors/commits?author=ehmicky\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/bhvngt\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/79074469?v=4?s=100\" width=\"100px;\" alt=\"const_var\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003econst_var\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#ideas-bhvngt\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"#question-bhvngt\" title=\"Answering Questions\"\u003e💬\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/abrenneke\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/342540?v=4?s=100\" width=\"100px;\" alt=\"Andy Brenneke\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAndy Brenneke\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#ideas-abrenneke\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"#question-abrenneke\" title=\"Answering Questions\"\u003e💬\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/tgfisher4\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/49082176?v=4?s=100\" width=\"100px;\" alt=\"Graham Fisher\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eGraham Fisher\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/ehmicky/modern-errors/issues?q=author%3Atgfisher4\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/renzor-fist\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/117486829?v=4?s=100\" width=\"100px;\" alt=\"renzor\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003erenzor\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#question-renzor-fist\" title=\"Answering Questions\"\u003e💬\u003c/a\u003e \u003ca href=\"#ideas-renzor-fist\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/eugene1g\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/147496?v=4?s=100\" width=\"100px;\" alt=\"Eugene\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eEugene\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/ehmicky/modern-errors/commits?author=eugene1g\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/ehmicky/modern-errors/issues?q=author%3Aeugene1g\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://uk.linkedin.com/in/jonathanmarkchambers/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/49592?v=4?s=100\" width=\"100px;\" alt=\"Jonathan Chambers\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJonathan Chambers\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/ehmicky/modern-errors/commits?author=jmchambers\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"https://github.com/ehmicky/modern-errors/issues?q=author%3Ajmchambers\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/heyhey123-git\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/156066831?v=4?s=100\" width=\"100px;\" alt=\"heyhey123\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eheyhey123\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/ehmicky/modern-errors/issues?q=author%3Aheyhey123-git\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n","funding_links":[],"categories":["JavaScript","browser","Uncategorized"],"sub_categories":["Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehmicky%2Fmodern-errors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fehmicky%2Fmodern-errors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehmicky%2Fmodern-errors/lists"}