# errors/codes _(no submodules)_ ## Purpose This module declares the stable error-code registry for `@suaveplan/broadcast-channel`. Every error the package throws surfaces one of four codes under the `BROADCAST_CHANNEL.*` namespace so downstream consumers — loggers, problem+json responders, retry wrappers, i18n resolvers — can map the failure to a retry policy, HTTP status, or translation key without re-implementing the classifier. The registry is built via `defineCodes` from `@suaveplan/error`, which yields a frozen `{ REASON: "BROADCAST_CHANNEL.REASON" }` record at compile time. The literal-typed union `BroadcastChannelErrorCode` is preserved through the public surface, so `instanceof BroadcastChannelError` narrows cleanly and exhaustive `switch (err.code)` blocks stay type-checkable. ## Features - Four reasons: `CHANNEL_CLOSED`, `MESSAGE_MALFORMED`, `PAYLOAD_TOO_LARGE`, `STORAGE_FAILED`. - Four typed subclasses extending `SuaveplanError`. - Every code is thrown from at least one production code path (tested). - Optional context carriers (`sizeBytes`, `maxBytes`) on the payload-too-large variant. - `BroadcastChannelError` abstract base for ergonomic `instanceof` checks. ## Usage: Basic ```ts import { BROADCAST_CHANNEL_CODES, BroadcastChannelClosedError, } from "@suaveplan/broadcast-channel"; try { channel.send("greet", "hi"); } catch (err) { if ( err instanceof BroadcastChannelClosedError && err.code === BROADCAST_CHANNEL_CODES.CHANNEL_CLOSED ) { // open the channel first } } ``` ## Usage: Advanced ```ts import { BROADCAST_CHANNEL_CODES, BroadcastChannelError, type BroadcastChannelErrorCode, } from "@suaveplan/broadcast-channel"; function classify(err: unknown): "retry" | "drop" | "alert" { if (!(err instanceof BroadcastChannelError)) return "alert"; const code: BroadcastChannelErrorCode = err.code; switch (code) { case BROADCAST_CHANNEL_CODES.CHANNEL_CLOSED: return "retry"; case BROADCAST_CHANNEL_CODES.MESSAGE_MALFORMED: return "drop"; case BROADCAST_CHANNEL_CODES.PAYLOAD_TOO_LARGE: return "drop"; case BROADCAST_CHANNEL_CODES.STORAGE_FAILED: return "alert"; default: return "alert"; } } ``` ## API Reference - `const BROADCAST_CHANNEL_CODES` — frozen `{ readonly CHANNEL_CLOSED, MESSAGE_MALFORMED, PAYLOAD_TOO_LARGE, STORAGE_FAILED }` mapped to namespaced strings. - `type BroadcastChannelErrorCode` — union of every code string. - `abstract class BroadcastChannelError extends SuaveplanError`. - `class BroadcastChannelClosedError` — `send` on a not-open / closed channel. - `class BroadcastChannelMessageMalformedError` — Zod validation failure at the boundary. - `class BroadcastChannelPayloadTooLargeError` — outbound payload over `maxMessageBytes`. Optional `sizeBytes` / `maxBytes` opts populate `context`. - `class BroadcastChannelStorageFailedError` — fallback transport `StorageLike` rejected. ## Implementation Notes `defineCodes` returns a `Readonly>` so the output object can be passed straight into `Object.freeze` consumers and the keys typecheck as `BroadcastChannelErrorCode`. Each subclass routes through `pickOpts` to strip `undefined` fields out of `SuaveplanErrorOptions` so the underlying `SuaveplanError` constructor sees only the keys the caller explicitly set — this matters for the OTel `toSpanEvent` adapter, which omits absent attributes rather than emitting `null`. The `BroadcastChannelPayloadTooLargeError` constructor merges `sizeBytes` / `maxBytes` into the user-supplied `context` so log lines and span attributes carry both the offender's size and the configured budget without the caller having to remember to attach them.