← ClaudeAtlas

design-an-error-modellisted

Use when designing how a backend service (or a fleet of services) reports errors — a typed exception hierarchy (one base + per-status subclasses carrying statusCode/message/data), a validation-error flattener wired into the global ValidationPipe, a global exception filter that maps every throw to ONE uniform response body (+ trace id, severity-based logging, hide internals on 5xx), an RPC/microservice filter twin, and a log-and-swallow decorator for fire-and-forget handlers. NestJS reference, framework-flexible.
kennguyen887/agent-foundation · ★ 1 · Web & Frontend · score 77
Install: claude install-skill kennguyen887/agent-foundation
# Design an error model One consistent error contract for a service (and ideally the whole fleet): typed exceptions → a global filter → one response shape, so clients parse errors the same way and logs are uniform. Examples NestJS/TS, neutral `@org` scope; the base class is `AppException`. principle → **▸ Example** → **▸ Other stacks**. This is the content of the shared `infra-exception` package (see `structure-a-shared-backend-lib`); it pairs with `write-cross-cutting-code` (the filter is a cross-cutting primitive) and `write-service-code` §7 (logging). ## Core principle **Never let raw framework/vendor errors reach the client, and never hand-shape error JSON in handlers.** Throw a *typed* exception that carries its status + a stable body; one global filter turns every throw — typed, validation, or unexpected — into the **same response shape** with a trace id. Handlers just `throw new NotFoundError(...)`; they never build an error response. ## 1. A typed exception hierarchy - **One base exception** extends the framework's HTTP exception and carries a structured payload `{ statusCode, message, data? }`, plus a `prepareResponse(traceId)` that produces the wire body. **One subclass per HTTP status** fixes the code so call sites read intent, not numbers. ```ts export class AppException extends HttpException { constructor(private readonly info: { statusCode: HttpStatus; message: string; data?: unknown }) { super(info.message, info.statusCode); } prepa