npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rootly-runtime

v1.2.7

Published

Minimal runtime error tracking for Node.js production apps

Readme

rootly-runtime

Runtime error tracking SDK for Node.js applications. Captures production errors and sends them to your Rootly dashboard with full context and stack traces.

What is this?

rootly-runtime is a lightweight error tracking library that monitors your Node.js application for errors and automatically reports them to Rootly. When an error occurs in production, you'll see it in your IDE with the exact line of code that caused it, along with the full stack trace and request context.

IMPORTANT: This SDK is currently in beta. While we've tested it extensively, some errors may not be captured reliably across all platforms and scenarios. We do not guarantee 100% error detection. Manual capture() calls are the most reliable method across all environments.

Installation

npm install rootly-runtime

Basic Setup

Add these two lines at the very top of your application entry point (before any other imports):

const { init } = require('rootly-runtime');

init({
  apiKey: process.env.ROOTLY_API_KEY
});

That's it. The SDK will now automatically capture uncaught exceptions and unhandled promise rejections.

How It Works

Once initialized, the SDK:

  1. Registers global error handlers for uncaughtException and unhandledRejection
  2. Captures error details (message, stack trace, environment info)
  3. Sends error reports to Rootly's backend via HTTP POST
  4. Deduplicates identical errors (10-second window)
  5. Rate limits to prevent overwhelming your dashboard (20 errors per 60 seconds)

The SDK is designed to fail silently - if it encounters any issues sending error reports, it will not crash your application.

Configuration Options

init({
  apiKey: 'your-api-key',        // Required: Get this from your Rootly dashboard
  environment: 'production',     // Optional: 'production' or 'preview' (default: NODE_ENV)
  debug: false                   // Optional: Enable debug logging (default: false)
});

Environment Detection

The SDK normalizes environment values:

  • 'production' or 'prod''production'
  • Anything else → 'preview'

If you don't specify an environment, it uses process.env.NODE_ENV or defaults to 'production'.

Usage Examples

Automatic Error Capture

The SDK automatically captures these error types:

// Uncaught exceptions
throw new Error('Something went wrong');

// Unhandled promise rejections
Promise.reject(new Error('Async operation failed'));

// Async/await errors (if not caught)
async function fetchData() {
  throw new Error('Database connection failed');
}

Manual Error Capture

For errors you catch in try/catch blocks, use capture() to report them:

const { capture } = require('rootly-runtime');

try {
  const result = riskyOperation();
} catch (error) {
  // Send to Rootly with additional context
  capture(error, {
    user_id: '12345',
    action: 'checkout',
    cart_total: 99.99
  });
  
  // Handle the error gracefully
  res.status(500).json({ error: 'Payment processing failed' });
}

The second parameter accepts any JSON-serializable object. This context will appear in your Rootly dashboard alongside the error.

Severity Levels

You can specify error severity as the third parameter:

// Error (default)
capture(error, { user_id: '123' }, 'error');

// Warning
capture(new Error('Deprecated API used'), { endpoint: '/old-api' }, 'warning');

// Info
capture(new Error('Migration completed'), { records: 1000 }, 'info');

Express Middleware

For Express applications, use the error handler middleware to automatically capture 5xx errors:

const express = require('express');
const { init, expressErrorHandler } = require('rootly-runtime');

init({ apiKey: process.env.ROOTLY_API_KEY });

const app = express();

// Your routes
app.get('/api/users', (req, res) => {
  // Your code
});

// Add Rootly error handler BEFORE your final error handler
app.use(expressErrorHandler());

// Your final error handler
app.use((err, req, res, next) => {
  res.status(500).json({ error: err.message });
});

The middleware only captures errors when res.statusCode >= 500. It ignores 4xx errors (validation, authentication, etc.) and adds Express-specific context like HTTP method, path, and status code.

Function Wrapping

Wrap functions to automatically capture and re-throw errors:

const { wrap } = require('rootly-runtime');

// Synchronous function
const processPayment = wrap((amount) => {
  if (amount < 0) throw new Error('Invalid amount');
  return { success: true };
});

// Async function
const fetchUser = wrap(async (userId) => {
  const response = await fetch(`/api/users/${userId}`);
  if (!response.ok) throw new Error('User not found');
  return response.json();
});

// Errors are captured AND re-thrown
try {
  await fetchUser('123');
} catch (error) {
  // Error was sent to Rootly, now handle it
  console.error('Failed to fetch user');
}

Serverless Functions (Vercel, AWS Lambda)

For serverless environments, use flush() to ensure error reports complete before the function exits:

const { init, capture, flush } = require('rootly-runtime');

init({ apiKey: process.env.ROOTLY_API_KEY });

export default async function handler(req, res) {
  try {
    const result = await processRequest(req);
    res.status(200).json(result);
  } catch (error) {
    await capture(error, { path: req.url });
    await flush(); // Wait for error to be sent
    res.status(500).json({ error: 'Internal server error' });
  }
}

Note: Automatic error capture (uncaught exceptions, unhandled rejections) may not work reliably in Vercel serverless functions due to platform limitations. Use manual capture() calls for guaranteed error reporting in serverless environments.

Platform Support

The SDK has been tested on:

  • Traditional Node.js servers
  • Express.js applications
  • Render deployments
  • Railway deployments
  • GitHub Actions
  • Vercel (manual capture only)
  • AWS Lambda (manual capture recommended)

Beta Notice: Error capture reliability varies across platforms. Some errors may not be captured consistently. Manual capture() is the most reliable method.

API Reference

init(options)

Initialize the SDK. Must be called before any other SDK functions.

Parameters:

  • options.apiKey (string, required) - Your Rootly API key
  • options.environment (string, optional) - Environment name ('production' or 'preview')
  • options.debug (boolean, optional) - Enable debug logging

Returns: void

capture(error, context?, severity?)

Manually capture an error.

Parameters:

  • error (Error | string, required) - The error to capture
  • context (object, optional) - Additional context (must be JSON-serializable)
  • severity ('error' | 'warning' | 'info', optional) - Error severity (default: 'error')

Returns: Promise

wrap(fn)

Wrap a function to automatically capture errors.

Parameters:

  • fn (Function, required) - Function to wrap (sync or async)

Returns: Wrapped function that captures and re-throws errors

expressErrorHandler()

Express middleware for automatic 5xx error capture.

Returns: Express error handler middleware

flush(timeout?)

Wait for all pending error reports to complete.

Parameters:

  • timeout (number, optional) - Max wait time in milliseconds (default: 5000)

Returns: Promise

Environment Variables

The SDK automatically detects commit SHA from these environment variables:

  • RENDER_GIT_COMMIT (Render)
  • RAILWAY_GIT_COMMIT_SHA (Railway)
  • VERCEL_GIT_COMMIT_SHA (Vercel)
  • GITHUB_SHA (GitHub Actions)

You can also set ROOTLY_API_URL to use a custom backend endpoint (defaults to https://rootly-backend.onrender.com).

Error Deduplication

The SDK deduplicates errors based on a fingerprint generated from:

  • Error message
  • Stack trace
  • File path and line number

Identical errors within a 10-second window are deduplicated to prevent spam.

Rate Limiting

To prevent overwhelming your dashboard, the SDK limits error reporting to 20 errors per 60 seconds. Additional errors are dropped silently.

Fail-Silent Design

The SDK is designed to never crash your application. If error reporting fails (network issues, invalid API key, etc.), the SDK logs the failure (if debug mode is enabled) and continues silently.

TypeScript Support

The SDK includes TypeScript type definitions:

import { init, capture, wrap, expressErrorHandler, flush } from 'rootly-runtime';

init({
  apiKey: process.env.ROOTLY_API_KEY!,
  environment: 'production',
  debug: true
});

capture(new Error('Type-safe error'), { userId: 123 }, 'error');

Troubleshooting

Errors not appearing in dashboard

  1. Check your API key is correct
  2. Enable debug mode: init({ apiKey: '...', debug: true })
  3. Check console for SDK debug messages
  4. Verify network connectivity to Rootly backend
  5. Try manual capture() to test connectivity

Serverless functions timing out

Use flush() to wait for error reports:

await capture(error);
await flush(2000); // Wait up to 2 seconds

Too many errors being captured

The SDK automatically rate limits to 20 errors per 60 seconds. If you're hitting this limit, you may have a critical bug causing error loops.

License

MIT

Support

For issues and questions:

  • GitHub: https://github.com/Lancerhawk/Project-Rootly
  • Documentation: https://rootly-webapp.vercel.app/docs

Changelog

See CHANGELOG.md for version history and release notes.