errorcore
Capturing Errors

Automatic Capture

Automatic capture is the default path for unhandled exceptions and framework-level error surfaces. Once the SDK is initialized, it hooks into uncaughtException and unhandledRejection process events. No additional wiring is needed.

initialization
import errorcore from "errorcore";

errorcore.init({
  service: "billing-api",
  transport: { type: "file", path: "./errors.ndjson" },
  allowUnencrypted: true,
});

After init() runs, any unhandled throw or rejected promise produces an incident package:

unhandled exception
// captured without any try/catch or manual call
setTimeout(() => {
  throw new Error("worker loop failed");
}, 5000);
unhandled rejection
async function syncAccounts() {
  const res = await fetch("https://upstream.internal/accounts");
  if (!res.ok) throw new Error(`upstream returned ${res.status}`);
}

// the rejected promise is captured automatically
syncAccounts();

If a middleware integration is active (Express, Fastify, etc.), errors that propagate through the framework's error handler are captured there instead, with the request context already attached. The process-level hooks act as a safety net for anything that escapes the framework boundary.

What gets included

Each automatically captured incident contains:

  • the error type, message, and full stack trace
  • request metadata, if the error occurred inside a request scope
  • ordered IO timeline when IO recording is active
  • local variables at the throw site, if captureLocalVariables is enabled
  • any tracked state reads from the same request

Shutdown behavior

When an uncaughtException fires, the SDK attempts to deliver the incident before the process exits. By default it waits up to 1500ms. Adjust this with uncaughtExceptionExitDelayMs if your transport needs more time:

exit delay
errorcore.init({
  service: "worker",
  transport: { type: "http", url: "https://collector.example.com/v1/errors" },
  encryptionKey: process.env.ERRORCORE_KEY,
  uncaughtExceptionExitDelayMs: 3000,
});

If delivery fails during shutdown, the package is written to the dead-letter store and retried on the next startup.

On this page