# koa-better-error-handler

> A better error-handler for Lad and Koa. Makes `ctx.throw` awesome (best used with koa-404-handler)

Latest version **12.0.0** (published 2026-01-02) · MIT license · 0 weekly downloads

## Install

```sh
npm install koa-better-error-handler
pnpm add koa-better-error-handler
yarn add koa-better-error-handler
bun add koa-better-error-handler
```

## Health

**Score 45/100 (D)** — status: stable.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

## Facts

| | |
|---|---|
| Version | 12.0.0 |
| Published | 2026-01-02 |
| First published | 2016-07-28 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Node | >= 18 |
| Dependencies | 8 |
| Unpacked size | 28.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 56 |
| Author | Nick Baugh |
| Maintainers | niftylettuce, titanism |
| Keywords | 404, 500, async, await, better, boom, context, ctx, custom, error, error-handler, errors, es7, flash, handler, handling, koa, messages, override, promises, stripe |

## Links

- npm: https://www.npmjs.com/package/koa-better-error-handler
- Repository: https://github.com/ladjs/koa-better-error-handler
- Issues: https://github.com/ladjs/koa-better-error-handler/issues
- npm.io page: https://npm.io/package/koa-better-error-handler

## Dependencies (8)

- [statuses](https://npm.io/package/statuses.md) ^2.0.1
- [camelcase](https://npm.io/package/camelcase.md) 6
- [@hapi/boom](https://npm.io/package/@hapi/boom.md) ^10.0.1
- [capitalize](https://npm.io/package/capitalize.md) ^2.0.4
- [html-to-text](https://npm.io/package/html-to-text.md) ^9.0.5
- [toidentifier](https://npm.io/package/toidentifier.md) ^1.0.1
- [humanize-string](https://npm.io/package/humanize-string.md) 2
- [fast-safe-stringify](https://npm.io/package/fast-safe-stringify.md) ^2.1.1

## Alternatives

- [@commercetools/sync-actions](https://npm.io/package/@commercetools/sync-actions.md) — 25.1K weekly downloads
- [cwait](https://npm.io/package/cwait.md) — 21.4K weekly downloads
- [@ledgerhq/hw-app-cosmos](https://npm.io/package/@ledgerhq/hw-app-cosmos.md) — 4.2K weekly downloads
- [@financial-times/o-loading](https://npm.io/package/@financial-times/o-loading.md) — 2.8K weekly downloads
- [fa](https://npm.io/package/fa.md) — 185 weekly downloads

## Recent versions

- 12.0.0 (latest) — 2026-01-02
- 11.0.4 — 2023-02-14
- 11.0.3 — 2023-02-01
- 11.0.2 — 2023-01-31
- 11.0.1 — 2023-01-31
- 11.0.0 — 2023-01-20
- 10.0.8 — 2023-01-15
- 10.0.7 — 2022-07-05
- 10.0.6 — 2022-07-03
- 10.0.5 — 2022-07-02
- 10.0.4 — 2022-07-02
- 10.0.3 — 2022-07-02
- 10.0.2 — 2022-07-02
- 10.0.1 — 2022-07-01
- 10.0.0 — 2022-07-01
- … 32 more at https://npm.io/package/koa-better-error-handler/versions

## README

# koa-better-error-handler

[![build status](https://github.com/ladjs/koa-better-error-handler/actions/workflows/ci.yml/badge.svg)](https://github.com/ladjs/koa-better-error-handler/actions/workflows/ci.yml)
[![code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo)
[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
[![made with lass](https://img.shields.io/badge/made_with-lass-95CC28.svg)](https://lass.js.org)
[![license](https://img.shields.io/github/license/ladjs/koa-better-error-handler.svg)](LICENSE)

> A better error-handler for [Lad][] and [Koa][].  Makes `ctx.throw` awesome (best used with [koa-404-handler][])


## Index

* [Features](#features)
* [Install](#install)
* [Usage](#usage)
  * [API](#api)
  * [Web App](#web-app)
* [User-Friendly Responses](#user-friendly-responses)
* [HTML Error Lists](#html-error-lists)
* [License](#license)


## Features

* Detects Node.js DNS errors (e.g. `ETIMEOUT` and `EBADFAMILY`) and sends 408 Client Timeout error
* Detects Mongoose errors and sends 408 Client Timeout error
* Detects common programmer mistakes by detecting errors of TypeError, SyntaxError, ReferenceError, RangeError, URIError, and EvalError and yields generic "Internal Server Error" (only applies to production mode)
* Detects Redis errors (e.g. ioredis' MaxRetriesPerRequestError) and sends 408 Client Timeout error
* Uses [Boom][boom] for making error messages beautiful (see [User Friendly Responses](#user-friendly-responses) below)
* Simply a better error handler (doesn't remove all headers [like the built-in one does][gh-issue])
* Doesn't make all status codes 500 ([like the built-in Koa error handler does][gh-500-issue])
* Supports Flash messages and preservation of newly set session object
* Fixes annoying redirect issue where flash messages were lost upon an error being thrown
* Supports [HTML Error Lists](#html-error-lists) using `<ul>` for Mongoose validation errors with more than one message
* Makes `ctx.throw` beautiful messages (e.g. `ctx.throw(404)` will output a beautiful error object :hibiscus:)
* Supports `text/html`, `application/json`, and `text` response types
* Supports and recommends use of [mongoose-beautiful-unique-validation][mongoose-beautiful-unique-validation]


## Install

```bash
npm install --save koa-better-error-handler
```


## Usage

> You should probably be using this in combination with [koa-404-handler][] too!

The package exports a function which accepts four arguments (in order):

* `cookiesKey` - defaults to `false`
* `logger` - defaults to `console`
* `useCtxLogger` - defaults to `true`
* `stringify` - defaults to `fast-safe-stringify` (you can also use `JSON.stringify` or another option here if preferred)

If you pass a `cookiesKey` then support for sessions will be added. You should always set this argument's value if you are using cookies and sessions (e.g. web server).

We recommend to use [Cabin][] for your `logger` and also you should use its middleware too, as it will auto-populate `ctx.logger` for you to make context-based logs easy.

Note that this package only supports `koa-generic-session`, and does not yet support `koa-session-store` (see the code in [index.js](index.js) for more insight, pull requests are welcome).

### API

> No support for sessions, cookies, or flash messaging:

```js
const errorHandler = require('koa-better-error-handler');
const Koa = require('koa');
const Router = require('koa-router');
const koa404Handler = require('koa-404-handler');

// initialize our app
const app = new Koa();

// override koa's undocumented error handler
app.context.onerror = errorHandler();

// specify that this is our api
app.context.api = true;

// use koa-404-handler
app.use(koa404Handler);

// set up some routes
const router = new Router();

// throw an error anywhere you want!
router.get('/404', ctx => ctx.throw(404));
router.get('/500', ctx => ctx.throw(500));

// initialize routes on the app
app.use(router.routes());

// start the server
app.listen(3000);
console.log('listening on port 3000');
```

### Web App

> Built-in support for sessions, cookies, and flash messaging:

```js
const errorHandler = require('koa-better-error-handler');
const Koa = require('koa');
const redis = require('redis');
const RedisStore = require('koa-redis');
const session = require('koa-generic-session');
const flash = require('koa-connect-flash');
const convert = require('koa-convert');
const Router = require('koa-router');
const koa404Handler = require('koa-404-handler');

// initialize our app
const app = new Koa();

// define keys used for signing cookies
app.keys = ['foo', 'bar'];

// initialize redis store
const redisClient = redis.createClient();
redisClient.on('connect', () => app.emit('log', 'info', 'redis connected'));
redisClient.on('error', err => app.emit('error', err));

// define our storage
const redisStore = new RedisStore({
  client: redisClient
});

// add sessions to our app
const cookiesKey = 'lad.sid';
app.use(
  convert(
    session({
      key: cookiesKey,
      store: redisStore
    })
  )
);

// add support for flash messages (e.g. `req.flash('error', 'Oops!')`)
app.use(convert(flash()));

// override koa's undocumented error handler
app.context.onerror = errorHandler(cookiesKey);

// use koa-404-handler
app.use(koa404Handler);

// set up some routes
const router = new Router();

// throw an error anywhere you want!
router.get('/404', ctx => ctx.throw(404));
router.get('/500', ctx => ctx.throw(500));

// initialize routes on the app
app.use(router.routes());

// start the server
app.listen(3000);
console.log('listening on port 3000');
```


## User-Friendly Responses

> Example Request:

```bash
curl -H "Accept: application/json" http://localhost/some-page-does-not-exist
```

> Example Response:

```json
{
  "statusCode": 404,
  "error": "Not Found",
  "message":"Not Found"
}
```


## Prevent Errors From Being Automatically Translated

As of v3.0.5, you can prevent an error from being automatically translated by setting the error property of `no_translate` to have a value of `true`:

```js
function middleware(ctx) {
  const err = Boom.badRequest('Uh oh!');
  err.no_translate = true; // <----
  ctx.throw(err);
}
```


## HTML Error Lists

If you specify `app.context.api = true` or set `ctx.api = true`, and if a Mongoose validation error message occurs that has more than one message (e.g. multiple fields were invalid) – then `err.message` will be joined by a comma instead of by `<li>`.

Therefore if you *DO* want your API error messages to return HTML formatted error lists for Mongoose validation, then set `app.context.api = false`, `ctx.api = false`, or simply make sure to not set them before using this error handler.

```js
try {
  // trigger manual validation
  // (this allows us to have a 400 error code instead of 500)
  await company.validate();
} catch (err) {
  ctx.throw(Boom.badRequest(err));
}
```

> With error lists:

```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "<ul class=\"text-left mb-0\"><li>Path `company_logo` is required.</li><li>Gig description must be 100-300 characters.</li></ul>"
}
```

> Without error lists:

```json
{
  "statusCode":400,
  "error":"Bad Request",
  "message":"Path `company_logo` is required., Gig description must be 100-300 characters."
}
```


## API Friendly Messages

By default if `ctx.api` is true, then [html-to-text](https://github.com/werk85/node-html-to-text) will be invoked upon the `err.message`, thus converting all the HTML markup into text format.

You can also specify a base URI in the environment variable for rendering as `process.env.ERROR_HANDLER_BASE_URL`, e.g. `ERROR_HANDLER_BASE_URL=https://example.com` (omit trailing slash), and any HTML links such as `<a href="/foo/bar/baz">Click here</a>` will be converted to `[Click here][1]` with a `[1]` link appended of `https://example.com/foo/bar/baz`.


## License

[MIT](LICENSE) © [Nick Baugh](http://niftylettuce.com/)


##

[boom]: https://github.com/hapijs/boom

[gh-issue]: https://github.com/koajs/koa/issues/571

[gh-500-issue]: https://github.com/koajs/koa/blob/e4bcdecef295d7adbf5cce1bdc09adc0a24117b7/lib/context.js#L94-L140

[mongoose-beautiful-unique-validation]: https://github.com/matteodelabre/mongoose-beautiful-unique-validation

[lad]: https://lad.js.org

[koa]: http://koajs.com/

[koa-404-handler]: https://github.com/ladjs/koa-404-handler

[cabin]: https://cabinjs.com

---
_Source: https://npm.io/package/koa-better-error-handler · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
