npm package: @glassops/error
Description: Canonical error classes used throughout GlassOps applications.
Author: GlassOps Limited
Latest version: 1.0.0

# Error

> `@glassops/error`

The GlassOps Error System provides a deterministic, taxonomy‑driven foundation for all operational and programmer errors across the platform. Every error class maps to a canonical `ApiErrorCode`, resolves to a single HTTP status code, and exposes a frozen, typed context object to ensure contributor‑safe behavior with zero runtime ambiguity.

This package exists to eliminate guesswork: every error is explicit, structured, and serializable in a uniform way—no ad‑hoc throwing, no inconsistent shapes, no drifting status codes.

## Purpose and design principles

The system is built around a few non‑negotiable principles:

- Deterministic taxonomy — Every error has a stable `ApiErrorCode` and a single, authoritative HTTP status code.
- Typed, immutable context — Error metadata is frozen and typed at construction time to prevent accidental mutation.
- Operational semantics — Errors distinguish between expected failures (e.g., validation, auth) and programmer errors (e.g., invariants, internal bugs).
- Dual serialization modes — Safe external JSON for clients, and rich internal JSON for observability and debugging.
- Contributor safety — No subclass can drift from the taxonomy or introduce ambiguous behavior.

This ensures that errors behave the same way everywhere—API handlers, background jobs, logging pipelines, and monitoring systems all receive the same predictable structure.

## Core components

### GlassOpsError (base class)

All error types extend `GlassOpsError<T>`, which provides:

- `code`: Canonical `ApiErrorCode`.
- `statusCode`: Resolved from `API_ERROR_MAP`.
- `context`: Frozen metadata describing the failure.
- `isOperational`: Indicates whether the error is expected or a bug.
- `cause`: Native error chaining support.
- `toJSON()`: Safe external serialization.
- `toInternalJson()`: Full debugging metadata including stack and nested cause.

This class enforces the invariants that keep the system mechanically honest.

## Error taxonomy

Each error subclass corresponds to a specific domain of failure. Categories include:

- Authentication & Authorization
  - `UnauthorizedError` (401)
  - `ForbiddenError` (403)
  - `PaymentRequiredError` (402)
- Routing & Request Handling
  - `MethodNotAllowedError` (405)
  - `TooManyRequestsError` (429)
  - `UriTooLongError` (414)
  - `TimeoutError` (408)
- Validation
  - `ValidationError` (400): Normalizes express‑validator output into deterministic ValidationIssue[]
- Media & Uploads
  - `UnsupportedMediaTypeError` (415)
  - `ContentTooLargeError` (413)
- Server & Infrastructure
  - `InternalServerError` (500)
  - `ServiceUnavailableError` (503)
  - `GatewayTimeoutError` (504)
  - `BadGatewayError` (502)
  - `TemplateError` (500)
  - `DatabaseError` (500)
  - `ConfigError` (500)

Each class exposes a typed context object tailored to its domain (e.g., service, operation, requiredPermission, missingVariables, etc.).

### API error map

`API_ERROR_MAP` is the single source of truth mapping every `ApiErrorCode` to its HTTP status code. This prevents drift between error classes, middleware, and transport layers.

Any new error subclass must add a corresponding entry to this map.

## Validation normalization

ValidationError wraps express‑validator’s heterogeneous output into a stable structure:

- issues: ValidationIssue[]
- count: number

Each issue includes:

- failing field
- human‑readable message
- location (body, query, etc.)
- provided value
- optional nested issues

This ensures consistent error reporting regardless of how complex the input shape is.

## Serialization Modes

### External JSON (toJSON())

Safe for:

- API responses
- External logs
- Client‑side debugging

Includes:

- `code`
- `name`
- `message`
- `statusCode`
- `context`
- `cause` (message only)

### Internal JSON (toInternalJson())

Safe for:

- Observability pipelines
- Structured logging
- Debugging tools

Includes everything from `toJSON()` plus:

- Full cause metadata
- Stack trace

## Adding a New Error Class

To introduce a new error type:

- Define a new `ApiErrorCode` in `types.ts`.
- Add the `code` to `status` mapping in `api-error-map.ts`.
- Create a subclass of `GlassOpsError<T>` with:
  - A clear, deterministic context shape
  - A canonical message
  - No runtime branching
- Document it with a uniform banner and JSDoc block.

This ensures the taxonomy remains complete and mechanically honest.

## Example Usage

```ts
import { UnauthorizedError } from '@glassops/error';

function requireAuth(token?: string) {
    if (!token) {
        throw new UnauthorizedError('Missing token', { reason: 'missing-token' });
    }
}
```

Errors thrown anywhere in the system can be safely serialized, logged, or returned to clients without special handling.

## Why This System Exists

Ad‑hoc error handling leads to:

- Inconsistent shapes
- Mismatched status codes
- Untyped metadata
- Ambiguous logs
- Brittle client behavior

The GlassOps Error System eliminates all of that by enforcing a single, deterministic contract for every error the platform can produce.
It’s not just an error library — it’s a taxonomy, a protocol, and a guarantee.