# @suaveplan/error - Foundation error substrate — SuaveplanError base class, stable code registry, cause-chain traversal, Zod-validated wire format (JSON + MessagePack), redaction, OTel span-event adapter, i18n resolver hook. Zero @suaveplan/* deps. ## Summary Foundation error substrate for Suaveplan. Every non-testing `@suaveplan/*` package extends this library's `SuaveplanError` base class and uses its stable code registry. The package provides: `SuaveplanError` — an abstract base with literal-typed discriminant codes, injectable clock, context bag, traceId, and cause chaining; `defineCodes(namespace, reasons)` — a frozen, literal-typed registry that makes error codes refactor-safe; `walkCauses(err)` — a cycle-safe, depth-bounded generator for traversing nested error causes; lossless JSON and binary wire formats (`toJSON`/`fromJSON`/`toBinary`/`fromBinary`) with Zod validation; `markSensitive`/`unwrapSensitive` for redaction at serialization boundaries; `toSpanEvent` for OpenTelemetry `exception` span events without an OTel SDK import; and a `setMessageResolver` hook for i18n. Zero `@suaveplan/*` runtime or peer dependencies — this is the lowest-level package in the stack. ## Documentation tree - [package-error](./src/base/package-error.md) — `ErrorPackageError` is the one concrete `SuaveplanError` subclass shipped by `@suaveplan/error` itself. It carries the… - [suaveplan-error](./src/base/suaveplan-error.md) — `SuaveplanError` is the abstract base class that every non-testing package in the project extends. It standardises the… - [causes](./src/causes/walk-causes.md) — _(no submodules)_ - [walk-causes](./src/causes/walk-causes.md) — _(no submodules)_ - [define-codes](./src/codes/define-codes.md) — `defineCodes` is the canonical way to declare a stable, literal-typed error code registry for a package. It takes a nam… - [error-codes](./src/codes/error-codes.md) — `ERROR_CODES` is the package-local registry for `@suaveplan/error` itself. It enumerates every failure mode the foundat… - [i18n](./src/i18n/resolver.md) — _(no submodules)_ - [resolver](./src/i18n/resolver.md) — _(no submodules)_ - [otel](./src/otel/to-span-event.md) — _(no submodules)_ - [to-span-event](./src/otel/to-span-event.md) — _(no submodules)_ - [redact](./src/redact/sensitive.md) — _(no submodules)_ - [sensitive](./src/redact/sensitive.md) — _(no submodules)_ - [from-binary](./src/serialize/from-binary.md) — `fromBinary` is the decode counterpart to `toBinary`. It accepts a `Uint8Array` produced by `toBinary` (or any compatib… - [from-json](./src/serialize/from-json.md) — `fromJSON` is the decode counterpart to `toJSON`. It Zod-validates the incoming payload against `wireErrorSchema` and r… - [to-binary](./src/serialize/to-binary.md) — `toBinary` encodes any error-shaped value into a compact byte payload suitable for binary transports (message queues, W… - [to-json](./src/serialize/to-json.md) — `toJSON` serialises any error-shaped value to a wire-safe plain object that round-trips losslessly back through `fromJS… - [walk-causes](./src/causes/walk-causes.md) — _(no submodules)_- [define-codes](./src/codes/define-codes.md) — `defineCodes` is the canonical way to declare a stable, literal-typed error code registry for a package. It takes a nam… - [error-codes](./src/codes/error-codes.md) — `ERROR_CODES` is the package-local registry for `@suaveplan/error` itself. It enumerates every failure mode the foundat… - [i18n](./src/i18n/resolver.md) — _(no submodules)_- [resolver](./src/i18n/resolver.md) — _(no submodules)_- [otel](./src/otel/to-span-event.md) — _(no submodules)_- [to-span-event](./src/otel/to-span-event.md) — _(no submodules)_- [redact](./src/redact/sensitive.md) — _(no submodules)_- [sensitive](./src/redact/sensitive.md) — _(no submodules)_- [from-binary](./src/serialize/from-binary.md) — `fromBinary` is the decode counterpart to `toBinary`. It accepts a `Uint8Array` produced by `toBinary` (or any compatib… - [from-json](./src/serialize/from-json.md) — `fromJSON` is the decode counterpart to `toJSON`. It Zod-validates the incoming payload against `wireErrorSchema` and r… - [to-binary](./src/serialize/to-binary.md) — `toBinary` encodes any error-shaped value into a compact byte payload suitable for binary transports (message queues, W… - [to-json](./src/serialize/to-json.md) — `toJSON` serialises any error-shaped value to a wire-safe plain object that round-trips losslessly back through `fromJS… - [walk-causes](./src/causes/walk-causes.md) — _(no submodules)_- [define-codes](./src/codes/define-codes.md) — `defineCodes` is the canonical way to declare a stable, literal-typed error code registry for a package. It takes a nam… - [error-codes](./src/codes/error-codes.md) — `ERROR_CODES` is the package-local registry for `@suaveplan/error` itself. It enumerates every failure mode the foundat… - [i18n](./src/i18n/resolver.md) — _(no submodules)_- [resolver](./src/i18n/resolver.md) — _(no submodules)_- [otel](./src/otel/to-span-event.md) — _(no submodules)_- [to-span-event](./src/otel/to-span-event.md) — _(no submodules)_- [redact](./src/redact/sensitive.md) — _(no submodules)_- [sensitive](./src/redact/sensitive.md) — _(no submodules)_- [from-binary](./src/serialize/from-binary.md) — `fromBinary` is the decode counterpart to `toBinary`. It accepts a `Uint8Array` produced by `toBinary` (or any compatib… - [from-json](./src/serialize/from-json.md) — `fromJSON` is the decode counterpart to `toJSON`. It Zod-validates the incoming payload against `wireErrorSchema` and r… - [to-binary](./src/serialize/to-binary.md) — `toBinary` encodes any error-shaped value into a compact byte payload suitable for binary transports (message queues, W… - [to-json](./src/serialize/to-json.md) — `toJSON` serialises any error-shaped value to a wire-safe plain object that round-trips losslessly back through `fromJS… - [walk-causes](./src/causes/walk-causes.md) — _(no submodules)_- [define-codes](./src/codes/define-codes.md) — `defineCodes` is the canonical way to declare a stable, literal-typed error code registry for a package. It takes a nam… - [error-codes](./src/codes/error-codes.md) — `ERROR_CODES` is the package-local registry for `@suaveplan/error` itself. It enumerates every failure mode the foundat… - [i18n](./src/i18n/resolver.md) — _(no submodules)_- [resolver](./src/i18n/resolver.md) — _(no submodules)_- [otel](./src/otel/to-span-event.md) — _(no submodules)_- [to-span-event](./src/otel/to-span-event.md) — _(no submodules)_- [redact](./src/redact/sensitive.md) — _(no submodules)_- [sensitive](./src/redact/sensitive.md) — _(no submodules)_- [from-binary](./src/serialize/from-binary.md) — `fromBinary` is the decode counterpart to `toBinary`. It accepts a `Uint8Array` produced by `toBinary` (or any compatib… - [from-json](./src/serialize/from-json.md) — `fromJSON` is the decode counterpart to `toJSON`. It Zod-validates the incoming payload against `wireErrorSchema` and r… - [to-binary](./src/serialize/to-binary.md) — `toBinary` encodes any error-shaped value into a compact byte payload suitable for binary transports (message queues, W… - [to-json](./src/serialize/to-json.md) — `toJSON` serialises any error-shaped value to a wire-safe plain object that round-trips losslessly back through `fromJS… - [walk-causes](./src/causes/walk-causes.md) — _(no submodules)_- [define-codes](./src/codes/define-codes.md) — `defineCodes` is the canonical way to declare a stable, literal-typed error code registry for a package. It takes a nam… - [error-codes](./src/codes/error-codes.md) — `ERROR_CODES` is the package-local registry for `@suaveplan/error` itself. It enumerates every failure mode the foundat… - [i18n](./src/i18n/resolver.md) — _(no submodules)_ - [resolver](./src/i18n/resolver.md) — _(no submodules)_- [otel](./src/otel/to-span-event.md) — _(no submodules)_ - [to-span-event](./src/otel/to-span-event.md) — _(no submodules)_- [redact](./src/redact/sensitive.md) — _(no submodules)_ - [sensitive](./src/redact/sensitive.md) — _(no submodules)_- [from-binary](./src/serialize/from-binary.md) — `fromBinary` is the decode counterpart to `toBinary`. It accepts a `Uint8Array` produced by `toBinary` (or any compatib… - [from-json](./src/serialize/from-json.md) — `fromJSON` is the decode counterpart to `toJSON`. It Zod-validates the incoming payload against `wireErrorSchema` and r… - [to-binary](./src/serialize/to-binary.md) — `toBinary` encodes any error-shaped value into a compact byte payload suitable for binary transports (message queues, W… - [to-json](./src/serialize/to-json.md) — `toJSON` serialises any error-shaped value to a wire-safe plain object that round-trips losslessly back through `fromJS… ## Install ```bash bun add @suaveplan/error ``` ## Highlights - **`SuaveplanError`** — abstract base with literal-typed code discriminants, injectable clock, context, traceId, cause - **`defineCodes(namespace, reasons)`** — frozen, literal-typed code registry - **`walkCauses(err)`** — cycle-safe, depth-bounded cause-chain generator - **`toJSON`/`fromJSON`/`toBinary`/`fromBinary`** — lossless, Zod-validated wire format; binary form is UTF-8-encoded canonical JSON, no external encoder - **`markSensitive` / `unwrapSensitive`** — redaction tagging applied at the serialization boundary - **`toSpanEvent`** — OpenTelemetry `exception` span event payload, no OTel SDK import - **`setMessageResolver`** — i18n hook; default resolver returns the key verbatim ## Foundation rules honoured - Zero `@suaveplan/*` runtime or peer deps - Runtime deps: `tslib`, `zod` - Zero Node / browser built-in references in `src/` (guarded by `tests/no-disallowed.test.ts`) - `sideEffects: false`, per-module subpath exports - 100% statement / branch / function / line coverage (guarded in `vitest.config.ts`) ## Usage ```ts import { defineCodes, SuaveplanError } from "@suaveplan/error"; export const AUTH_CODES = defineCodes("AUTH", [ "LOGIN.INVALID", "LOGIN.LOCKED", ] as const); export class AuthError extends SuaveplanError< (typeof AUTH_CODES)[keyof typeof AUTH_CODES] > { public constructor( code: (typeof AUTH_CODES)[keyof typeof AUTH_CODES], key: string, options?: ConstructorParameters[2] ) { super(code, key, options); } } throw new AuthError(AUTH_CODES["LOGIN.INVALID"], "error.auth.login.invalid", { context: { user: "alice" }, traceId: "trace-1", }); ``` ## Wire format `toJSON(err)` returns a plain object with `__suaveplanError: 1`, ready for JSON-safe transport. `fromJSON(value)` validates and reconstructs the payload. `toBinary` / `fromBinary` exchange the same content as a UTF-8 byte array. ## Testing ```bash bunx turbo lint typecheck test --filter=@suaveplan/error bunx turbo test:coverage --filter=@suaveplan/error ```