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

custom-error-creator

v1.1.1

Published

Create typed, structured error classes from simple definitions.

Readme

custom-error-creator

npm version GitHub CI bundle size

Create typed, structured error classes from simple definitions.

Why?

Lets you define errors declaratively and get back proper classes with:

  • Typed error codes — catch and handle errors by code, not by sniffing message strings
  • HTTP status codes — errors carry their status, so your error handler doesn't need a mapping table
  • Message templates — parameterised messages with compile-time checking of required params
  • PascalCase namesNOT_FOUND becomes NotFound in stack traces automatically
  • Clean stack traces — the error points at your throw site, not the class internals
  • Standard cause chaining — wrap underlying errors using the ES2022 cause option

I found myself using similar patterns for error handling in multiple projects, and this module encapsulates the common boilerplate into a simple, reusable API.

Install

npm install custom-error-creator

Quick start

import { createErrorClass } from "custom-error-creator";

const NotFound = createErrorClass({
  code: "NOT_FOUND",
  message: "Resource {resource} not found",
  status: 404,
});

throw new NotFound({ resource: "User" });
// NotFound: Resource User not found
//     at handler (/app/routes.ts:12:9)

API

createErrorClass(definition)

Creates a single error class from a definition.

const ValidationError = createErrorClass({
  code: "VALIDATION_ERROR",
  message: "{field} is invalid: {reason}",
  status: 400,
});

createErrorClassesByCode(definitions)

Creates multiple error classes at once, returned as an object keyed by code.

import { createErrorClassesByCode } from "custom-error-creator";

const errors = createErrorClassesByCode([
  { code: "NOT_FOUND", message: "Resource {resource} not found", status: 404 },
  { code: "UNAUTHORIZED", message: "Access denied", status: 401 },
  {
    code: "VALIDATION_ERROR",
    message: "{field} is invalid: {reason}",
    status: 400,
  },
]);

throw new errors.NOT_FOUND({ resource: "User" });
throw new errors.UNAUTHORIZED();
throw new errors.VALIDATION_ERROR({ field: "email", reason: "too short" });

createErrorClassesByName(definitions)

Creates multiple error classes at once, returned as an object keyed by PascalCase name.

import { createErrorClassesByName } from "custom-error-creator";

const errors = createErrorClassesByName([
  { code: "NOT_FOUND", message: "Resource {resource} not found", status: 404 },
  { code: "UNAUTHORIZED", message: "Access denied", status: 401 },
]);

throw new errors.NotFound({ resource: "User" });
throw new errors.Unauthorized();

isCustomError(error)

Type guard to check if an error is an instance of any error class created by this module.

Constructor signatures

The constructor is flexible depending on whether the message template has parameters.

Errors with template parameters

When the default message contains {param} placeholders, the params object is required:

const NotFound = createErrorClass({
  code: "NOT_FOUND",
  message: "Resource {resource} not found",
  status: 404,
});

// Params required — typed and checked at compile time
new NotFound({ resource: "User" });
new NotFound({ resource: "User" }, { cause: underlyingError });

// Custom message — params become optional and untyped
new NotFound("Thing not found");
new NotFound("{thing} is gone", { thing: "Widget" });
new NotFound("Gone", { cause: underlyingError });
new NotFound("{x} missing", { x: "y" }, { cause: underlyingError });

Errors without template parameters

const Unauthorized = createErrorClass({
  code: "UNAUTHORIZED",
  message: "Access denied",
  status: 401,
});

new Unauthorized();
new Unauthorized("Custom message");
new Unauthorized("Custom message", { cause: underlyingError });

Error instance properties

Every error instance has the standard Error properties plus:

const err = new NotFound({ resource: "User" });

err.message; // "Resource User not found"
err.name; // "NotFound"
err.code; // "NOT_FOUND"
err.status; // 404
err.stack; // stack trace pointing at the throw site
err.cause; // underlying error, if provided

Static class properties

Error classes also expose code and name as static properties, useful for comparisons without instantiating:

const NotFound = createErrorClass({
  code: "NOT_FOUND",
  message: "Resource {resource} not found",
  status: 404,
});

NotFound.code; // "NOT_FOUND"
NotFound.name; // "NotFound"

Error handling patterns

By code

try {
  await getUser(id);
} catch (err) {
  if (err.code === "NOT_FOUND") {
    // handle missing resource
  }
}

By instanceof

try {
  await getUser(id);
} catch (err) {
  if (err instanceof NotFound) {
    // handle missing resource
  }
}

Wrapping errors with cause

Use the standard cause option to chain underlying errors:

try {
  await db.query("SELECT ...");
} catch (err) {
  throw new NotFound({ resource: "User" }, { cause: err });
}

The cause is set using the native Error constructor option (ES2022), so it behaves identically to new Error("msg", { cause }) — non-enumerable and compatible with all standard tooling.

Reserved parameter names

The parameter name cause is reserved and cannot be used in message templates. This is enforced at both compile time and runtime:

// ❌ Compile error at definition time
const Bad = createErrorClass({
  code: "BAD",
  message: "Failed because {cause}",
  status: 500,
});

// ❌ Runtime error — throws immediately

Type safety

Template parameters are fully type-checked when using the default message:

const NotFound = createErrorClass({
  code: "NOT_FOUND",
  message: "Resource {resource} not found",
  status: 404,
});

new NotFound({ resource: "User" }); // ✅
new NotFound({ resorce: "User" }); // ❌ typo caught at compile time
new NotFound({}); // ❌ missing required param
new NotFound(); // ❌ params required

Instance properties are also typed:

const err = new NotFound({ resource: "User" });
err.code; // type: "NOT_FOUND"
err.status; // type: 404
err.name; // type: "NotFound"

License

MIT