• Stars
    star
    122
  • Rank 292,031 (Top 6 %)
  • Language
    JavaScript
  • Created about 13 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Error handling utilities for node

error

Wrap errors with more context.

Inspiration

This module is inspired by the go error libraries that have simple functions for creating & wrapping errors.

This is based on libraries like eris & pkg/errors

Older version of error

If you are looking for the older v7 version of error you should check v7.x branch

Using error with async / await

Check out resultify !

The rest of the examples use plain vanilla callbacks.

Motivation

Wrapping errors when bubbling up instead of just doing if (err) return cb(err) allows you to pass more context up the stack.

Common example include passing along parameters from the DB read related to the failure or passing along any context from the user in a HTTP request when doing a failure.

This can give you nice to read messages that include more information about the failure as it bubbles up.

There is more information about how to handle errors in this article Don't just check errors, handle them gracefully

If you want a deep dive into the difference between Programming and Operational errors please check out this guide

examples:

const { wrapf } = require('error')

function authenticatRequest(req) {
  authenticate(req.user, (err) => {
    if (err) {
      return cb(wrapf('authenticate failed', err))
    }
    cb(null)
  })
}

or

const { wrapf } = require('error')

function readFile(path, cb) {
  fs.open(path, 'r', (err, fd) => {
    if (err) {
      return cb(wrapf('open failed', err, { path }))
    }

    const buf = Buffer.alloc(64 * 1024)
    fs.read(fd, buf, 0, buf.length, 0, (err) => {
      if (err) {
        return cb(wrapf('read failed', err, { path }))
      }

      fs.close(fd, (err) => {
        if (err) {
          return cb(wrapf('close failed', err, { path }))
        }

        cb(null, buf)
      })
    })
  })
}

Structured errors

const { SError } = require('error')

class ServerError extends SError {}
class ClientError extends SError {}

const err = ServerError.create(
  '{title} server error, status={statusCode}', {
    title: 'some title',
    statusCode: 500
  }
)
const err2 = ClientError.create(
  '{title} client error, status={statusCode}', {
    title: 'some title',
    statusCode: 404
  }
)

Wrapped Errors

const net = require('net');
const { WError } = require('error')

class ServerListenError extends WError {}

var server = net.createServer();

server.on('error', function onError(err) {
  if (err.code === 'EADDRINUSE') {
    throw ServerListenFailedError.wrap(
      'error in server, on port={requestPort}', err, {
        requestPort: 3000,
        host: null
      }
    )
  } else {
    throw err;
  }
});

server.listen(3000);

Comparison to Alternatives.

There are alternative existing libraries for creating typed and wrapped errors on npm. Here's a quick comparison to some alternatives.

verror

This module takes inspiration from verror and adds improvements.

  • You can pass extra fields as meta data on the error
  • The templating forces dynamic strings to be extra fields.
  • Uses ES6 classes for inheritance. This gives your errors unique class names and makes them show up in heapdumps.
  • Has JSON.stringify support

[email protected]

This package used to have a completely different API on the 7.x branch.

  • New error module uses actual classes instead of dynamically monkey patching fields onto new Error()
  • Implementation is more static, previous code was very dynamic
  • Simpler API, see the message & properties in one place.
  • wrapf & errorf helpers for less boilerplate.

Hand writing Error sub classes.

You can create your own Error classes by hand. This tends to lead to 10-20 lines of boilerplate per error which is replace with one line by using the error module; aka

class AccountsServerFailureError extends SError {}
class ConnectionResetError extends WError {}

ono

The ono package has similar functionality with a different API

  • ono encourages plain errors instead of custom errors by default
  • error has zero dependencies
  • error is only one simple file. ono is 10.
  • error implementation is more static, ono is very dynamic.

Documentation

This package implements three classes, WError; SError & MultiError

You are expected to subclass either WError or SError;

  • SError stands for Structured Error; it's an error base class for adding informational fields to your error beyond just having a message.
  • WError stands for Wrapped Error; it's an error base class for when you are wrapping an existing error with more information.

The MultiError class exists to store an array of errors but still return a single Error; This is useful if your doing a parallel operation and you want to wait for them all to finish and do something with all of the failures.

Some utility functions are also exported:

  • findCauseByName; See if error or any of it's causes is of the type name.
  • fullStack; Take a wrapped error and compute a full stack.
  • wrapf; Utility function to quickly wrap
  • errorf; Utility function to quickly create an error
  • getInfo; Utility function to get the info for any error object. Calls err.info() if the method exists.

WError

Example:

class ServerListenError extends WError {}

ServerListenError.wrap('error in server', err, {
  port: 3000
})

When using the WError class it's recommended to always call the static wrap() method instead of calling the constructor directly.

Example (without cause message):

class ApplicationStartupError extends WError {}

ApplicationStartupError.wrap(
  'Could not start the application cleanly: {reason}',
  err,
  {
    skipCauseMessage: true,
    reason: 'Failed to read from disk'
  }
)

Setting skipCauseMessage: true will not append the cause error message but still make the cause object available.

const werr = new WError(message, cause, info)

Internal constructor, should pass a message string, a cause error and a info object (or null).

WError.wrap(msgTmpl, cause, info)

wrap() method to create error instances. This applies the string-template templating to msgTmpl with info as a parameter.

The cause parameter must be an error The info parameter is an object or null.

The info parameter can contain the field skipCauseMessage: true which will make WError not append : ${causeMessage} to the message of the error.

werr.type

The type field is the machine readable type for this error. Always use err.type and never err.message when trying to determine what kind of error it is.

The type field is unlikely to change but the message field can change.

werr.fullType()

Calling fullType will compute a full type for this error and any causes that it wraps. This gives you a long type string that's a concat for every wrapped cause.

werr.cause()

Returns the cause error.

werr.info()

Returns the info object passed on. This is merged with the info of all cause errors up the chain.

werr.toJSON()

The WError class implements toJSON() so that the JSON serialization makes sense.

WError.fullStack(err)

This returns a full stack; which is a concatenation of this stack trace and the stack trace of all causes in the cause chain

WError.findCauseByName(err, name)

Given an err and a name will find if the err or any causes implement the type of that name.

This allows you to check if a wrapped ApplicationError has for example a LevelReadError or LevelWriteError in it's cause chain and handle database errors differently from all other app errors.

SError

Example:

class LevelReadError extends SError {}

LevelReadError.create('Could not read key: {key}', {
  key: '/some/key'
})

When using the SError class it's recommended to always call the static create() method instead of calling the constructor directly.

const serr = new SError(message, info)

Internal constructor that takes a message string & an info object.

SError.create(messageTmpl, info)

The main way to create error objects, takes a message template and an info object.

It will use string-template to apply the template with the info object as a parameter.

SError.getInfo(error)

Static method to getInfo on a maybe error. The error can be null or undefined, it can be a plain new Error() or it can be a structured or wrapped error.

Will return err.info() if it exists, returns {} if its null and returns { ...err } if its a plain vanilla error.

serr.type

Returns the type field. The err.type field is machine readable. Always use err.type & not err.message when trying to compare errors or do any introspection.

The type field is unlikely to change but the message field can change.

serr.info()

Returns the info object for this error.

serr.toJSON()

This class can JSON serialize cleanly.

MultiError

Example:

class FanoutError extends MultiError {}

function doStuff (filePath, cb) {
  fanoutDiskReads(filePath, (errors, fileContents) => {
    if (errors && errors.length > 0) {
      const err = FanoutError.errorFromList(errors)
      return cb(err)
    }

    // do stuff with files.
  })
}

When using the MultiError class it's recommended to always call the static errorFromList method instead of calling the constructor directly.

Usage from typescript

The error library does not have an index.d.ts but does have full jsdoc annotations so it should be typesafe to use.

You will need to configure your tsconfig appropiately ...

{
  "compilerOptions": {
    ...
    "allowJs": true,
    ...
  },
  "include": [
    "src/**/*.js",
    "node_modules/error/index.js"
  ],
  "exclude": [
    "node_modules"
  ]
}

Typescript does not understand well type source code in node_modules without an index.d.ts by default, so you need to tell it to include the implementation of error/index.js during type checking and to allowJs to enable typechecking js + jsdoc comments.

Installation

npm install error

Contributors

  • Raynos

MIT Licenced

More Repositories

1

mercury

A truly modular frontend framework
JavaScript
2,818
star
2

http-framework

A web framework based purely on require('http')
JavaScript
523
star
3

xtend

extend like a boss
JavaScript
305
star
4

global

Require global variables
JavaScript
252
star
5

main-loop

A rendering loop for diffable UIs
JavaScript
172
star
6

leaked-handles

Detect any handles leaked in node
JavaScript
166
star
7

DOM-shim

Shims out the entire DOM4 API
JavaScript
155
star
8

function-bind

JavaScript
136
star
9

body

Body parsing
JavaScript
120
star
10

after

All the flow control you'll ever need
JavaScript
116
star
11

min-document

A minimal DOM implementation
JavaScript
109
star
12

jsig

From scratch type-checker
JavaScript
104
star
13

duplexer

Creates a duplex stream
JavaScript
95
star
14

observ

A observable value representation
JavaScript
74
star
15

observ-struct

An object with observable key value pairs
JavaScript
72
star
16

virtual-hyperscript

A DSL for creating virtual trees
JavaScript
59
star
17

topology

Different network topologies
JavaScript
57
star
18

dom-delegator

Decorate elements with delegated events
JavaScript
57
star
19

continuable

Idea for callbacks as values
JavaScript
54
star
20

live-reload

A live reload server & client
JavaScript
51
star
21

pd

Property Descriptors made easy
JavaScript
44
star
22

engine.io-stream

Wrap engine.io in a real stream interface
JavaScript
44
star
23

vdom-thunk

A thunk optimization for virtual-dom
JavaScript
42
star
24

stream-chat

Alpha chat app using streams for communication
JavaScript
40
star
25

resultify

Handle errors with async/await without try/catch.
JavaScript
38
star
26

graphics

Efficient data structures that represent renderable scenes
JavaScript
38
star
27

safe-json-parse

Parse JSON safely without throwing
JavaScript
36
star
28

webrtc-stream

WebRTC demo
JavaScript
34
star
29

level-livefeed

Live query a range in leveldb
JavaScript
34
star
30

http-works

A workshopper for http framework
JavaScript
32
star
31

tsdocstandard

Standard but also use TypeScript on JS files with jsdoc.
JavaScript
31
star
32

discovery-network

A peer to peer discovery network
JavaScript
31
star
33

geval

JavaScript
30
star
34

corsify

CORS up a route handler
JavaScript
29
star
35

itape

An interactive tape runner.
JavaScript
27
star
36

ncore

Core infrastructure for node.
JavaScript
26
star
37

send-data

send data through response
JavaScript
26
star
38

observ-array

An array containing observable values
JavaScript
26
star
39

append-only

Append only scuttlebutt structure
JavaScript
25
star
40

jsonml-stringify

Convert jsonml arrays to html strings
JavaScript
22
star
41

eslint-plugin-perf-standard

A set of custom plugins to enforce high performance JS
JavaScript
21
star
42

routes-router

Simplest request handler possible
JavaScript
21
star
43

for-each

A better forEach
JavaScript
21
star
44

auth-stream

Authorize access before exposing a stream
JavaScript
21
star
45

value-event

Create DOM event handlers that write to listeners
JavaScript
21
star
46

boot

Shoe & mux demux with reconnect!
JavaScript
20
star
47

stream-router

Easily route mdm streams
JavaScript
19
star
48

raynos-blog

My blog
JavaScript
19
star
49

jsconf2014-talk

Modular frontend with NPM & pals
JavaScript
19
star
50

whatwg-streams

JavaScript
17
star
51

deep-merge

Deep merge objects with custom merging logic
JavaScript
17
star
52

map-async

Asynchronously map over a list
JavaScript
17
star
53

data-channel

Turn a data channel into a stream
JavaScript
17
star
54

gens

Experimental usage of generators
JavaScript
17
star
55

level-cache

An in memory cache on top of leveldb
JavaScript
17
star
56

npm-bin-deps

NPR allows you to run your CLI dependencies without having a copy in node_modules.
JavaScript
16
star
57

serve-browserify

HTTP handler for serving browserify bundles
JavaScript
16
star
58

delta-stream

A stream that emits deltas in change
JavaScript
15
star
59

examplifier

Turn bland source code into interactive demos
JavaScript
15
star
60

distributed-map

A distributed key value store in the browser
JavaScript
14
star
61

clientmongo

Use the mongo API in the browser
JavaScript
14
star
62

multi-channel-mdm

Create persisted channels to broadcast data!
JavaScript
14
star
63

buffer-stream

A duplex stream that buffers writes
JavaScript
14
star
64

chain-stream

Chain stream operations together
JavaScript
14
star
65

fake-s3

a fake s3 server for testing purposes.
JavaScript
13
star
66

signal-channel

A signal channel that empowers webrtc
JavaScript
13
star
67

levelidb

A levelup interface on top of indexeddb
JavaScript
12
star
68

reduce

A better [].reduce
JavaScript
12
star
69

level-write-stream

A writeStream implementation for leveldb
JavaScript
12
star
70

frontend-framework

Building frontend apps with small modules
JavaScript
12
star
71

browserify-server

spin up browserify demos real easy
JavaScript
12
star
72

format-stack

Formats a stack with colors
JavaScript
12
star
73

feature

Feature detection for host objects
JavaScript
12
star
74

hash-router

A frontend router for the hash change event
JavaScript
11
star
75

promise-stream

A Promises/A implementation based on streams
JavaScript
11
star
76

html-delegator

Decorate elements with delegated events
JavaScript
11
star
77

ready-signal

A ready signal. Wait for ready and signal it's ready
JavaScript
11
star
78

ev-store

Stores event listeners and event handles on a DOM object
JavaScript
11
star
79

weakmap-shim

JavaScript
10
star
80

to-array

Turn an array like into an array
JavaScript
10
star
81

term-color

A lighter weight alternative to chalk
JavaScript
9
star
82

static-config

JavaScript
9
star
83

npm-less

JavaScript
9
star
84

eventemitter-light

It's a light event emitter
JavaScript
9
star
85

expiry-model

A scuttlebutt model that expires keys
JavaScript
9
star
86

http-methods

Handle multiple methods elegantly
JavaScript
9
star
87

mux-demux-shoe

Shoe and mux-demux come together!
JavaScript
9
star
88

validate-form

JavaScript
9
star
89

iterators

iterate over collections asynchronously
JavaScript
8
star
90

fake-sqs

Runs a fake SQS server on a HTTP port.
JavaScript
8
star
91

redirecter

JavaScript
8
star
92

seaport-proxy

Proxy all the seaports!
JavaScript
8
star
93

request-proxy

A version of request that's local to a fixed base uri
JavaScript
8
star
94

pre-bundled

A tool that pre bundles and re publishes npm dependencies
JavaScript
8
star
95

mongo-col

mongodb collection wrapper
JavaScript
8
star
96

tape-harness

A helper to run integration tests against an application
JavaScript
8
star
97

sockjs-stream

A streaming API for sockjs
JavaScript
7
star
98

add

Add two numbers
JavaScript
7
star
99

so642

JavaScript
7
star
100

composite

Compose functions together
JavaScript
7
star