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

@onlineapps/conn-infra-error-handler

v4.0.0

Published

Unified error handling with retry strategies, circuit breaker, and compensation patterns

Readme

Status: current Owns: the error-handling surface a business service is given — error-handler-core bound to that service's monitoring

Uniform: library/connector

Duty sections that apply:

  • all: L-MAIN, L-ENGINES, L-TESTS, L-TEST-SCRIPT, L-PACK-TESTS, L-PINS, L-NO-FILE-RANGE, L-CHANGELOG, L-README, L-README-REGION, L-CONSUMER
  • connector: L-CONNECTOR-ENV

@onlineapps/conn-infra-error-handler

Overview

Error handling connector for business services. Wraps @onlineapps/error-handler-core and integrates with @onlineapps/conn-base-monitoring for unified error handling and logging.

Note: This connector is for business services using ServiceWrapper. Infrastructure services should use @onlineapps/error-handler-core directly.

Installation

npm install @onlineapps/conn-infra-error-handler

Features

  • Error Classification - Automatic error type detection (TRANSIENT, BUSINESS, FATAL, etc.)
  • Retry Logic - Exponential backoff for transient errors
  • Circuit Breaker - Protection against cascading failures
  • Compensation - Rollback operations for failed workflows
  • Unified Logging - Structured error logging via monitoring-core

Architecture

This connector wraps @onlineapps/error-handler-core and integrates with @onlineapps/conn-base-monitoring:

conn-infra-error-handler (wrapper)
  └─> error-handler-core (core logic)
       └─> monitoring-core (logging)

See Error Handling Standard for the cross-cutting standard and package landscape.

Usage

Via ServiceWrapper — how a biz service gets one

A biz service does not construct this connector: ServiceWrapper builds one during initialize() and exposes it as wrapper.errorHandler. What the service declares is the errorHandling block inside the wrapper section of its config.json — not an errorHandling argument to the wrapper's constructor, which takes config, operations, serviceRoot and serviceBaseDir.

The wrapper reads five keys from that block and hands them on as the handling object described below: maxRetries, retryDelay, retryMultiplier, circuitBreakerEnabled, compensationEnabled. dlqEnabled was the sixth until the wrapper retired it — dead-lettering left this package with routeToDLQ() (see the CHANGELOG entry for it), so the key lost its only reader, and a config still writing it is now REFUSED by name rather than dropped in silence. Nothing of the wrapper's own travels on that object either: handling.mqClient, which it used to attach "for DLQ routing", went with the same reader. They are the wrapper's keys, not this package's — their meaning and their defaults live with service-wrapper, and a key the wrapper does not read changes nothing here.

Direct usage — import and construction

The module's default export is the connector class; there is no named ErrorHandlerConnector property on it. Alongside the class the module exports ErrorTypes, ErrorCodes, CircuitOpenError, create(config) and VERSION.

const ErrorHandlerConnector = require('@onlineapps/conn-infra-error-handler');
const { ErrorTypes, CircuitOpenError, VERSION } = require('@onlineapps/conn-infra-error-handler');
const { init: initMonitoring } = require('@onlineapps/conn-base-monitoring');

const monitoring = await initMonitoring({ serviceName: 'my-service', mode: 'light' });

const errorHandler = new ErrorHandlerConnector({
  serviceName: 'my-service',   // required
  monitoring,                  // required: conn-base-monitoring instance
  logger,                      // required: info/warn/error/debug
  serviceVersion: '1.0.0',     // optional
  environment: 'production',   // optional
  handling: {                  // optional, passed straight to error-handler-core
    maxRetries: 3,
    retryDelay: 1000,
    retryMultiplier: 2,
    circuitBreakerEnabled: true,
  }
});

Every required input is checked in the constructor, before the core is built — a missing one throws there, naming the key and the fix, never at first use:

  • serviceName — refused by the connector itself.
  • monitoring — refused by the connector itself.
  • logger — refused by assertLogger() of @onlineapps/logger-contract, which owns the contract; the message names ErrorHandlerConnector as the class the caller constructed.

Public methods

One line each; the parameters, return shapes and @throws are the generated detail in API.md (npm run docs renders it from the JSDoc in src/index.js — never edit it by hand).

  • classifyError(error) — the error's type from ErrorTypes.
  • shouldRetry(error, attempts) — whether that error at that attempt count is worth another try.
  • calculateBackoff(attempts) — the exponential backoff delay, in milliseconds, for an attempt.
  • executeWithRetry(fn, options) — runs an async function, retrying it per the retry handler.
  • executeWithCircuitBreaker(name, fn, options) — runs an async function behind a named circuit.
  • logError(errorData) — writes one unified error log entry.
  • handleError(errorData) — classify, log, and decide the action (retry / dlq / throw / compensate). The decision is returned to the caller; this package acts on none of it but compensation.
  • registerCompensation(operation, handler) — registers the rollback of an operation.
  • executeCompensation(operation, context) — runs the registered rollback, or returns null when none is registered.
  • createErrorResponse(error, context) — formats the standard error response for the perimeter.
  • getStats() — the live counters (errors, retries, compensations, circuit breaks, per type) plus the circuit states.
  • resetStats() — clears those counters.
  • getCircuitBreakerState(name) — the state of one circuit.
  • getAllCircuitBreakerStates() — the state of every circuit.

Circuit breaker refusal

An open circuit refuses the call itself — the action is not invoked. The refusal is a type with a code, never a sentence: CircuitOpenError from @onlineapps/error-handler-core, re-exported here so a consumer of this connector alone can recognise it. Every such refusal is counted in getStats().circuitBreaks.

const { CircuitOpenError } = require('@onlineapps/conn-infra-error-handler');

try {
  await errorHandler.executeWithCircuitBreaker('user-api', () => userAPI.getUser(id));
} catch (error) {
  if (error.code === 'CIRCUIT_OPEN') {
    // error.details.name === 'user-api'; error instanceof CircuitOpenError
  }
  throw error;
}

The optional third argument takes only the five options CircuitBreakerManager declares — timeout, errorThresholdPercentage, resetTimeout, rollingCountTimeout, rollingCountBuckets — each checked against its range before the circuit is created. An undeclared key is refused with the accepted ones listed.

Configuration

This package has no configuration of its own — no config schema, no defaults file, no environment variables it reads. What it accepts is the config object handed to the constructor above, and config.handling is passed straight through to @onlineapps/error-handler-core, which owns those keys and their defaults. The keys are listed in the constructor's JSDoc, rendered into API.md.

Error Types

Classification is @onlineapps/error-handler-core's and this connector only delegates to it. It reads, in order: an explicit error.type, then error.code, then the HTTP status in error.status — the field the error contract names (api/docs/biz/70-contracts/error-handling.md §1) — and only then the message patterns. error.statusCode is not read: an error branded with it alone falls through to the patterns and ends as UNKNOWN, which is not retried. Brand errors with code + status.

Transient Errors

Automatically retried:

  • Network errors (ECONNREFUSED, ETIMEDOUT)
  • Service unavailable (503)
  • Rate limiting (429)
  • An open circuit (CIRCUIT_OPEN) — the breaker heals itself after its reset timeout
  • Temporary database issues

Permanent Errors

Classified dlq on the first failure — handleError() returns the action, it routes nothing. Dead-lettering is the consumer policy of @onlineapps/mq-client-core, the only rail for biz and infra alike (mq-consumer-contract 002 bod 3):

  • Validation errors (400)
  • Authentication errors (401)
  • Not found errors (404)
  • Business logic errors

Error context and the log entry

logError() and handleError() take { moduleName, operation, error, context } and delegate to @onlineapps/error-handler-core, which builds the unified log entry — the error, the context, the handling decision and the metadata. The entry's shape is the core's (UnifiedLogSchema) and is not repeated here. context is passed through whole, so whatever a caller puts in it reaches the entry unchanged.

Testing

npm test                 # Run all tests
npm run test:unit        # Unit tier (tests/unit/**)

Dependencies

Declared in package.json, pinned exactly; this file does not repeat them. The monitoring instance the constructor requires is injected by the caller, so @onlineapps/conn-base-monitoring is not a dependency of this package.

Related Documentation


License: MIT — the published version is require('@onlineapps/conn-infra-error-handler').VERSION, read from package.json.