Skip to content

errorcoredev/errorcore

Repository files navigation

Errorcore

errorcore

Error monitoring with execution context for Node.js.

Errorcore captures the state around a failure so you can inspect what happened at the point an error was thrown. It focuses on request-level context, execution flow, and minimal setup.

What it does

  • Optionally captures local variables and arguments at the point an error is thrown
  • Tracks request context across async boundaries using AsyncLocalStorage
  • Records outbound IO in sequence
  • Attaches process and environment metadata with optional scrubbing
  • Encrypts payloads before transport
  • Buffers failed deliveries and retries when the network is available
  • Propagates W3C traceparent / tracestate headers for cross-service error context

Getting started

npm install errorcore

Add two lines to the top of your application entry point:

const errorcore = require('errorcore');
errorcore.init();

That's it. In development (NODE_ENV !== 'production'), errorcore defaults to stdout transport and unencrypted payloads. Throw an error and the captured payload prints to your terminal.

Quick start (fastest path)

npm install errorcore
npx errorcore init --quickstart
node errorcore-test.js

Framework middleware

// Express
const { expressMiddleware } = require('errorcore');
app.use(expressMiddleware());

// Fastify
const { fastifyPlugin } = require('errorcore');
fastify.register(fastifyPlugin);

// Koa
const { koaMiddleware } = require('errorcore');
app.use(koaMiddleware());

Production setup

Before deploying, configure a transport and encryption key:

// errorcore.config.js
module.exports = {
  transport: {
    type: 'http',
    url: 'https://collector.example.com/v1/errors',
    authorization: 'Bearer <token>',
    protocol: 'auto',
  },
  encryptionKey: process.env.ERRORCORE_DEK,
  macKey: process.env.ERRORCORE_MAC_KEY,
};

Generate a key: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

HTTP collector transport defaults to protocol: 'auto': HTTPS collectors try HTTP/2 first and fall back to HTTP/1.1 only when negotiation fails; plain HTTP uses HTTP/1.1 only and still requires allowPlainHttpTransport: true. Set protocol: 'http1' to force HTTP/1.1 or protocol: 'http2' to require HTTPS HTTP/2. The SDK does not instrument application HTTP/2 servers or clients in this release.

Manual propagation helpers are available when framework middleware is not enough:

const errorcore = require('errorcore');

errorcore.withTraceContext({ traceparent, tracestate, method: 'POST', url: '/job' }, () => {
  const headers = errorcore.getTraceHeaders();
  // attach headers.traceparent / headers.tracestate to outbound work
});

This is W3C propagation and package metadata only. There is no span API, exporter, OpenTelemetry bridge, tracing UI, ingestion layer, reconstruction layer, default-on locals, or identity extraction in this SDK release.

Database driver tiers

Errorcore records DB query events differently depending on your runtime environment.

Tier 1: Plain Node.js (Express, Fastify, Koa, NestJS, raw http): automatic. No config needed. All recorders install against the same require() graph the app uses.

Tier 2: Single-graph bundlers (Vite SSR, esbuild, plain webpack): automatic if the driver is not tree-shaken, or pass explicit references:

errorcore.init({
  drivers: { pg: require('pg'), mongodb: require('mongodb') },
});

Tier 3: Next.js App Router: externalize drivers from the webpack bundle:

// next.config.js
module.exports = {
  serverExternalPackages: ['pg', 'mongodb', 'mysql2', 'ioredis'],
};

Without this, the DB timeline will not populate. The startup diagnostic will report warn(bundled-unpatched). HTTP inbound, HTTP outbound, and fetch (undici) recording work in all three tiers.

Startup diagnostic

At startup, errorcore prints one line listing the state of each recorder:

[errorcore] 0.2.0 node=20.11.0 recorders: http-server=ok http-client=ok undici=ok net=ok dns=ok pg=skip(not-installed) mongodb=warn(bundled-unpatched) mysql2=skip(not-installed) ioredis=skip(not-installed)

Three states: ok (active), skip(<reason>) (intentionally inactive, no action needed), warn(<reason>) (wanted to install but couldn't, action required). When warns are present, the output grows to 3–6 lines with one actionable guidance line per warn state. Suppress the entire block with config.silent: true.

Next.js middleware capture

To capture errors and optionally non-2xx responses from Clerk-style middleware rejections, wrap your middleware with withNextMiddleware:

import { withNextMiddleware } from 'errorcore/nextjs';
import { clerkMiddleware } from '@clerk/nextjs/server';

export default withNextMiddleware(clerkMiddleware());

Control which response status codes trigger a capture:

errorcore.init({
  captureMiddlewareStatusCodes: [500, 502, 503, 504], // or 'all', or 'none' (default)
});

undefined returns (pass-through middleware) are never captured regardless of this setting. The ALS context started by withNextMiddleware propagates automatically into the downstream route handler.

Documentation

Running tests

npm test                                    # unit + always-on integration
npm run coverage                            # produce a coverage/ report
EC_INTEGRATION_PG=1    npm test             # add real-pg suite (needs Postgres)
EC_INTEGRATION_MYSQL=1 npm test             # add real-mysql suite (needs MySQL)
EC_SMOKE_NEXTJS=1      npm test             # run the Next.js smoke harness too

The mongodb integration suite uses mongodb-memory-server and runs unconditionally — the binary is downloaded once and cached at ~/.cache/mongodb-binaries. The ioredis suite runs against an in-process RESP-2 stub so it always runs too.

The pg and mysql2 suites are gated behind environment variables because they need a reachable database. CI does not run them; see CONTRIBUTING.md for the local docker / podman one-liners.

Coverage baseline (recorded 2026-05-01): 73.9% statements, 64.52% branches, 80.94% functions, 74.95% lines. The threshold is intentionally not enforced; the report is observability-only. Run npm run coverage and open coverage/index.html for the per-file breakdown.

Security

Report vulnerabilities via issues or privately.

Encryption key rotation is supported via previousEncryptionKeys in the config. See the Key rotation runbook for the operational sequence.

License

PolyForm Small Business 1.0.0. Free for individuals and companies under $1M revenue. Commercial license required above that threshold.

About

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors