result-patternlisted
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" |