Node.js Error & Exception Tracking

Typical installation time: 3 minutes

Hi there! You’ve found Honeybadger’s guide to Node.js error and exception tracking. Once installed, Honeybadger will automatically report errors from your Node.js application.

Heads up! Between callbacks, promises, event emitters, and timers, error-handling in Node.js is a complex and difficult field, but we’re here to help! Our Node.js library tries to catch as many different kinds of errors as possible with minimal configuration; if you encounter problems setting it up or find any gaps, feel free to open an issue.

Installation

Source CodeIssues

First, install the npm package:

sh
npm install @honeybadger-io/js --save

Then, require the honeybadger module and configure your API key:

javascript
const Honeybadger = require('@honeybadger-io/js'); Honeybadger.configure({ apiKey: '[ YOUR API KEY HERE ]' });

By default Honeybadger will be notified automatically of all unhandled errors which crash your node processes. Many applications catch errors, however, so you may want to set up some additional framework integrations.

Framework integrations

Express and Express-style frameworks

Errors which happen in Express or Connect apps can be automatically reported to Honeybadger by installing our middleware. The requestHandler middleware must be added before your other app middleware, while the errorHandler must be added after all app middleware and routes, but before any custom error handling middleware:

javascript
app.use(Honeybadger.requestHandler); // Use *before* all other app middleware. // Any other middleware and routes app.use(myMiddleware); app.get("/", (req, res) => {...}); app.use(Honeybadger.errorHandler); // Use *after* all other app middleware // Your custom error handling middleware app.use(myErrorMiddleware);

You can follow a similar pattern for most frameworks which use Express-style middleware:

Restify

js
const server = restify.createServer(); server.use(Honeybadger.requestHandler); // Other middleware and routes... server.on('restifyError', Honeybadger.errorHandler);

Sails.js

For Sails.js, use Honeybadger.errorHandler to report errors from within your custom serverError response.

js
const Honeybadger = require('@honeybadger-io/js'); module.exports = function serverError(optionalData) { if (_.isError(optionalData)) { Honeybadger.errorHandler(optionalData, this.req); return res.status(500).send(optionalData.stack); } };

You should also add the Honeybadger.requestHandler at the start of your middleware chain so asynchronous context can be correctly tracked between requests:

js
// in config/http.js module.exports.http = { middleware: { order: [ 'honeybadgerContext', // other middleware... ], honeybadgerContext: Honeybadger.requestHandler, }, };

Non-Express-style frameworks

For frameworks that don’t use Express-style middleware, Honeybadger will still capture unhandled exceptions automatically, but you may need to add a few lines of code to capture other kinds of errors and use the context feature properly. See the section on Tracking Context below.

AWS Lambda

To automatically report errors which happen in your AWS Lambda functions, wrap your Lambda handlers in Honeybadger.lambdaHandler():

javascript
async function myHandler(event, context) { // ... } exports.handler = Honeybadger.lambdaHandler(myHandler);

Check out our example AWS Lambda project for a list of handlers with different settings.

Timeout Warning

If your Lambda function hits its time limit, it will get killed by AWS Lambda without completing. Honeybadger can notify you when your function is about time out. By default, this will be when there are only 50 milliseconds left to reach the limit. You can override this with the timeoutWarningThresholdMs setting:

javascript
Honeybadger.configure({ timeoutWarningThresholdMs: 1000 });

You can disable the timeout warning with the reportTimeoutWarning setting:

javascript
Honeybadger.configure({ reportTimeoutWarning: false });

To manually report errors in a serverless environment, use Honeybadger.notifyAsync. Read more below.

Manually Reporting Errors

Honeybadger reports unhandled exceptions by default. You can also manually notify Honeybadger of errors and other events in your application code:

javascript
try { // ...error producing code... } catch(error) { Honeybadger.notify(error); }

Honeybadger.notify implements a fire-and-forget approach, which means that you can call the function and continue execution in your application code without waiting for the error to be reported. This is OK for most applications, but in some environments this can cause problems when the execution environment could be terminated before the report is sent to Honeybadger. For this reason, you may use Honeybadger.notifyAsync which is a promise-based implementation of notify and will resolve only after the report is sent:

javascript
async function doSomething() { try { // ...error producing code... } catch(error) { await Honeybadger.notifyAsync(error); } }

See the full documentation for more options.

Tracking Context

You can add contextual information to your error reports to make debugging easier:

javascript
Honeybadger.setContext({ query: searchQuery, });

When an error is captured (manually or automatically), the context will be sent along in the error report and displayed in the Context section of the Honeybadger UI.

Important: in apps like web servers that handle multiple requests at the same time, you need to properly isolate each request’s context. For middleware-based frameworks like Express, this is done automatically when you use the requestHandler middleware. For other frameworks, you’ll need to wrap your request and error handlers in Honeybadger.withRequest() method and pass in the request object. Here are examples in some popular frameworks:

Fastify

Fastify doesn’t support middleware by default, but you can use the preHandler hook instead. You’ll also need to add a custom error handler (and be sure to wrap it in Honeybadger.withRequest):

js
fastify.addHook('preHandler', Honeybadger.requestHandler); fastify.setErrorHandler((err, req, reply) => Honeybadger.withRequest(req, () => { Honeybadger.notify(err); reply.send({message: "error"}) }));

AdonisJS

For AdonisJS, you’ll need to do three (easy) steps:

  • Create a middleware that wraps your request handlers with withRequest()). You can generate a middleware with adonis make:middleware HoneybadgerContext (v4) or node ace make:middleware HoneybadgerContext (v5):
js
// Adonis v4: app/Middleware/HoneybadgerContext.js // Adonis v5: app/Middleware/HoneybadgerContext.ts class HoneybadgerContext { async handle ({ request, response }, next) { await Honeybadger.withRequest(request, next) } }
  • Register the middleware:
js
// Adonis v4: in start/kernel.js const globalMiddleware = [ 'App/Middleware/HoneybadgerContext' ] // Adonis v5: in start/kernel.ts Server.middleware.register([ () => import('App/Middleware/HoneybadgerContext'), ])
  • In your exception handler’s report() method, make sure to use withRequest(). (On Adonis v4, you may need to generate an exception handler with adonis make:ehandler):
js
// Adonis v4: app/Exceptions/Handler.js // Adonis v5: app/Exceptions/Handler.ts class ExceptionHandler extends BaseExceptionHandler { // ... async report (error, { request }) { Honeybadger.withRequest(request, () => Honeybadger.notify(error)) } }

Hapi

In Hapi, you’ll need to wrap your request handlers in withRequest, as well as add an onPreResponse extension to report errors.

javascript
server.route({ method: 'POST', path: '/search', handler: async (request, h) => Honeybadger.withRequest(request, () => { Honeybadger.setContext({ query: request.payload.searchQuery }); return ...; }) }); server.ext('onPreResponse', (request, h) => Honeybadger.withRequest(request, () => { if (!request.response.isBoom) { return h.continue; } Honeybadger.notify(request.response); return h.continue; }));

Identifying Users

Honeybadger can track what users have encountered each error. To identify the current user in error reports, add a user identifier and/or email address with Honeybadger.setContext:

javascript
Honeybadger.setContext({ user_id: 123, user_email: 'user@example.com' });

We’ll surface this info in a special “Affected Users” section in the Honeybadger UI.

Tracking Deploys

Honeybadger can also keep track of application deployments, and link errors to the version which the error occurred in. Here’s a simple curl script to record a deployment:

sh
HONEYBADGER_ENV="production" \ HONEYBADGER_REVISION="git SHA/project version" \ HONEYBADGER_API_KEY="project api key" \ curl -g "https://api.honeybadger.io/v1/deploys?deploy[environment]=$HONEYBADGER_ENV&deploy[local_username]=$USER&deploy[revision]=$HONEYBADGER_REVISION&api_key=$HONEYBADGER_API_KEY"

Be sure that the same revision is also configured in the honeybadger.js library. Read more about deploy tracking in the API docs.

Uncaught Exceptions

Honeybadger’s default uncaught exception handler logs the error and exits the process after notifying Honeybadger of the uncaught exception. You can change the default handler by replacing the afterUncaught config callback with a new handler function. Honeybadger will still be notified before your handler is invoked. Note that it’s important to exit the process cleanly if you replace the handler; see Warning: using ‘uncaughtException’ correctly for additional information.

Examples

javascript
Honeybadger.configure({ afterUncaught: (err) => { doSomethingWith(err); process.exit(1); } });

Disable Honeybadger’s uncaught error handler

To disable Honeybadger’s handler entirely (restoring Node’s default behavior for uncaught exceptions), use the enableUncaught option when calling Honeybadger.configure for the first time:

javascript
Honeybadger.configure({ apiKey: '[ YOUR API KEY HERE ]' enableUncaught: false });

Source Map Support

Honeybadger can automatically translate your production stack traces if you provide a source map for each release of your application. Learn more about source maps.

Honeybadger also supports Node’s experimental --source-map-support flag as of version 14+. If you run node with --source-map-support (and are generating source maps in your build), your stack traces should be automatically translated before they are sent to Honeybadger.

Sample Application

If you’d like to see the library in action before you integrate it with your apps, check out our sample Node.js/Express application.

You can deploy the sample app to your Heroku account by clicking this button:

Deploy

Don’t forget to destroy the Heroku app after you’re done so that you aren’t charged for usage.

The code for the sample app is available on Github, in case you’d like to read through it, or run it locally.