Skip to main content

introduction

Typed, registry-driven error classes for TypeScript. Branded codes, secret-safe serialization, framework-agnostic, zero dependencies.

Overview

@gentleduck/error builds one error class per subsystem from a plain object literal: a registry mapping string codes to HTTP status numbers. The class it returns is fully typed: which codes exist, what metadata each one carries, and whether metadata is required, all inferred from the registry, with no separate type declaration to keep in sync.

Loading diagram...

bun add @gentleduck/error
import { createErrorKit, detail, fault } from '@gentleduck/error'

const REGISTRY = {
  NOT_FOUND: 404,
  RATE_LIMITED: detail<{ retryAfter: number }>(429),
  STORAGE_FAILED: fault<{ cause?: string }>(500),
} as const satisfies Record<string, number>

const kit = createErrorKit('AppError', REGISTRY)
export const AppError = kit.ErrorClass
export const throwAppError = kit.throwError

throw new AppError('RATE_LIMITED', { retryAfter: 60 })
// err.status === 429, err.code === 'RATE_LIMITED'
// err.toJSON() -> { ok: false, error: { code: 'RATE_LIMITED', status: 429, retryAfter: 60 } }

Full walkthrough: Getting started.


Why a registry, not a class hierarchy

The usual alternative is one subclass per error kind (NotFoundError extends AppError), which scales linearly in files and forces every catch site to chain instanceof checks in the right order. A registry keeps every code, its status, and its metadata shape in one literal that is also the map a caller reads to know what a subsystem can raise. Object.keys(REGISTRY) is the exhaustive list, not a guess from grepping extends. Two kits never satisfy each other's instanceof, even with identical registries, since each call to createErrorKit declares its own class. Details: Core concepts.

Zero dependencies

packages/duck-error has no runtime dependencies. typescript is an optional peer, needed only for the types. It runs anywhere JavaScript does: server, browser, edge runtimes. See Browser and isomorphic usage.


All the docs

Concepts

Using it

Reference

Framework integrations