← ClaudeAtlas

result-patternlisted

Result/error discipline for domain and service logic — business outcomes return `Result<T,E>`, never throw; one unwrap at the transport boundary. Applies when working on backend/domain TypeScript code.
g-bastianelli/nuthouse · ★ 0 · AI & Automation · score 65
Install: claude install-skill g-bastianelli/nuthouse
# subroutine — Result / error discipline Applies to domain/service logic and transport boundaries (backend services, domain libs, RPC/HTTP handlers) — not React UI code. How success and failure travel through the code: domain/business logic **returns errors, never throws them**; the throw happens once, at the transport boundary. The repo's own `AGENTS.md` wins if it defines a different shape — read it first. ## The Result type ```ts export type Result<T, E> = { ok: true; value: T } | { ok: false; error: E }; export function ok<T>(value: T): Result<T, never> { return { ok: true, value }; } export function err<E>(error: E): Result<never, E> { return { ok: false, error }; } ``` If the repo already exports a `Result`/`ok`/`err` (e.g. from a shared types package), **use the repo's** — never redeclare it. ## Where each layer lives 1. **Domain / service layer** — framework-pure (no HTTP, no router imports). Returns `Promise<Result<T, ResourceError>>`. Propagates failures by returning the `err(...)`, never by throwing a business error. ```ts async function listGateways(): Promise<Result<Gateway[], GatewaysError>> { const resolved = resolveTenantDb(); if (!resolved.ok) return resolved; // propagate, don't throw return ok(await resolved.value.query.gateways.findMany()); } ``` 2. **Error type** — a **discriminated union per resource**, `code` + variant fields: ```ts type GatewaysError = | { code: "NOT_FOUND"; resource: "tenant" |