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

@cogs/errors

v0.2.0

Published

A suite of error classes which help you throw the most appropriate error in any situation

Readme

@cogs/errors

⚡ Error Handling at a Glance

This library provides a structured, Joyent-style approach to error handling — helping teams write predictable, recoverable, and well-typed errors in Node.js and browser environments.

Core Ideas

  • Operational vs Programmer Errors Handle operational errors (network issues, bad input, unavailable services) gracefully. Let programmer errors (bugs, logic mistakes) crash fast and surface for debugging.
  • Consistent Delivery Use throw for sync code, and Promise rejection, callback, or error events for async code. Never mix both in one API.
  • Structured Errors Every class extends Error with meaningful name, code, and context (like statusCode or relatesToSystems).
  • Recover or Crash Intentionally Operational errors are known and loggable. Programmer errors should terminate — not silently fail.

Common Behavior

All classes share the same ergonomics:

  • Flexible constructors – pass a message, an options object, or both. Extra fields go under error.data.
  • Normalized codes – any code you provide is uppercased and stripped of illegal characters (e.g. foo barFOO_BAR).
  • Native cause support – chain root causes using { cause } per Node’s ErrorOptions.
try {
  await fetchUpstream()
} catch (cause) {
  throw new UpstreamServiceError("Partner API failed", {
    code: "PARTNER_API_DOWN",
    relatesToSystems: ["partner-api"],
    cause,
  })
}

TL;DR

  • Distinguish operational vs programmer errors
  • Deliver errors consistently
  • Use structured, contextual Error subclasses
  • Log and recover from operational errors
  • Let programmer errors crash safely

Error Handling Philosophy

This library follows the Joyent guide on Node.js error handling. It defines a consistent approach to distinguish operational errors (known, expected runtime failures) from programmer errors (bugs in logic), and to deliver and document them predictably.

Core Principles

  • Operational vs Programmer Errors

    • Operational errors are expected problems in normal operation — network failures, missing files, invalid user input, etc.
    • Programmer errors are bugs — invalid arguments, undefined variables, failed assertions, etc.
    • Handle operational errors gracefully; fix programmer errors and allow them to surface (or crash safely).
  • Consistent Error Delivery

    • Synchronous code: use throw.
    • Asynchronous code: reject a Promise, invoke a callback with an error, or emit an "error" event.
    • Avoid mixing sync throw and async error delivery in a single API.
  • Structured Error Objects

    • Extend the built-in Error class (or subclasses) and include meaningful name, message, and contextual properties.
    • Preserve stack traces, and wrap underlying causes instead of discarding them.
throw Object.assign(new Error("Database connection failed"), {
  name: "DatabaseError",
  host,
  port,
  cause: err,
})
  • Documentation
    • Each function should specify:
      • expected arguments and constraints
      • return values or results
      • possible errors and how they are delivered

OperationalError

The OperationalError class is the foundation for most other error types. “Operational” here means we understand why the error occurred — it’s part of normal, recoverable runtime behavior rather than a programming bug.

Use OperationalError (or one of its subclasses) to signal expected failures that your system can handle or report cleanly.

You can construct an operational error with a simple message:

throw new OperationalError("example message");

Or use an object form to include a unique code and other context:

throw new OperationalError({
  message: "example message",
  code: "EXAMPLE_CODE"
});

Error codes are normalized to uppercase, alphanumeric, and underscore-delimited.

error.message // "example message"
error.code    // "EXAMPLE_CODE"

You can also combine message and options:

throw new OperationalError("example message", { code: "EXAMPLE_CODE" });

Extra fields are collected under error.data:

const error = new OperationalError({
  message: "example message",
  code: "EXAMPLE_CODE",
  article: "d92acacb-ac53-4505-aa88-eae4b42de994"
});

error.data.article // "d92acacb-ac53-4505-aa88-eae4b42de994"

OperationalError.relatesToSystems

Stores a list of systems or services related to the error — typically dependencies that failed or returned unexpected data.

OperationalError.cause

Holds the root cause (another Error), preserving diagnostic context:

try {
  await fetch(upstream);
} catch (err) {
  throw new OperationalError("Upstream request failed", { cause: err });
}

OperationalError.isErrorMarkedAsOperational()

Utility to check whether an error is operational:

OperationalError.isErrorMarkedAsOperational(new OperationalError("x")); // true
OperationalError.isErrorMarkedAsOperational(new Error("x"));             // false

HttpError

Extends OperationalError to represent HTTP status errors.

throw new HttpError("example message"); // defaults to 500

Or with explicit data:

throw new HttpError({
  message: "Resource not found",
  statusCode: 404
});

You can also create it directly from a status code:

throw new HttpError(404);

Properties:

error.message       // "Resource not found"
error.statusCode    // 404
error.status        // 404
error.statusMessage // "Not Found"
error.code          // "HTTP_404"

Why not use http-errors?

Unlike http-errors, this class extends OperationalError, marking all HTTP errors as known by default. A code property is also set automatically, simplifying filtering and dashboard metrics.

DataStoreError

Represents an error while accessing a data store such as MongoDB, PostgreSQL, or Redis.

throw new DataStoreError("Could not connect to Redis");

or

throw new DataStoreError({
  code: "REDIS_CONNECTION_FAILED",
  message: "Could not connect to Redis",
});

UpstreamServiceError

Extends HttpError to represent upstream or third-party API failures.

throw new UpstreamServiceError("Content could not be fetched");

Defaults to HTTP 502 (“Bad Gateway”). You can specify details and related systems:

throw new UpstreamServiceError({
  code: "CONTENT_PIPELINE_FAILED",
  message: "Upstream service responded with a 503",
  statusCode: 503,
  relatesToSystems: ["cp-content-pipeline-graphql"]
});

UserInputError

Extends HttpError for client input validation errors (defaults to 400 Bad Request).

throw new UserInputError("Invalid email address");

Or with structured data:

throw new UserInputError({
  code: "REGISTRATION_INFO_INVALID",
  message: "Invalid email address"
});

BaseError

The abstract root class for all errors in this library. It behaves like OperationalError but is explicitly non-operational — intended for use inside low-level or library code where operational semantics don’t apply.

const error = new BaseError("Internal failure");
error.isOperational === false;

Supports the same properties as OperationalError:

throw new BaseError({
  message: "example message",
  code: "EXAMPLE_CODE",
  cause: new TypeError("example cause")
});

Summary

  • Distinguish operational vs programmer errors
  • Deliver errors consistently (throw vs async rejection)
  • Use structured Error objects with clear name, code, and context
  • Crash on programmer errors, recover from operational ones
  • Document error behavior in every API