# `error-codes` _(no submodules)_ ## Purpose This module declares the structured error-code registry for `@suaveplan/audio-engine-browser`. Every fault path inside the package raises a `BrowserAudioError` carrying one of the codes registered here — nothing in the public surface throws a bare `Error`. This gives consumers programmatic, stable handles for catching specific failure modes (`err.code === "AUDIO_ENGINE_BROWSER.CONTEXT_FAILED"`) and gives the OTel integration the structured payload it needs to tag spans and produce useful traces. The registry is intentionally **closed**: callers cannot register new codes at runtime. Adding a new code requires extending the literal tuple passed to `defineCodes(...)` and updating the metadata table in the same commit so the description, severity, and call site stay in lockstep. ## Features - Seven dotted codes covering context lifecycle, worklet loading, graph/node addressing, track addressing, offline render, dispose invariants, and sidechain bus cycles. - Frozen metadata table (`AUDIO_ENGINE_BROWSER_ERROR_METADATA`) keyed by code → `{ description, severity }`. - `BrowserAudioError` class extending `SuaveplanError` for cause-chain traversal, structured `context`, and OTel span-event integration. - Idempotent `registerBrowserAudioErrorCodes()` hook for symmetry with the rest of the error ecosystem. ## Usage: Basic Example ```ts import { AUDIO_ENGINE_BROWSER_CODES, BrowserAudioError, } from "@suaveplan/audio-engine-browser/error-codes"; throw new BrowserAudioError( AUDIO_ENGINE_BROWSER_CODES.NODE_NOT_FOUND, "audio-engine-browser.node-not-found", { context: { id: "missing-id" } }, ); ``` ## Usage: Advanced Example ```ts import { AUDIO_ENGINE_BROWSER_CODES, AUDIO_ENGINE_BROWSER_ERROR_METADATA, BrowserAudioError, } from "@suaveplan/audio-engine-browser/error-codes"; try { await adapter.init(); } catch (e) { if (e instanceof BrowserAudioError) { const meta = AUDIO_ENGINE_BROWSER_ERROR_METADATA[e.code]; logger.error({ code: e.code, severity: meta.severity, cause: e.cause }); if (e.code === AUDIO_ENGINE_BROWSER_CODES.CONTEXT_FAILED) { // fall back to Html5AudioFallback } } throw e; } ``` ## API Reference ### `AUDIO_ENGINE_BROWSER_CODES` Frozen object mapping bare keys (`CONTEXT_FAILED`, …) to their dotted codes (`"AUDIO_ENGINE_BROWSER.CONTEXT_FAILED"`, …). Produced by `defineCodes("AUDIO_ENGINE_BROWSER", …)`. ### `BrowserAudioErrorCode` Union of every dotted code in the registry. ### `AUDIO_ENGINE_BROWSER_ERROR_METADATA` `Readonly>`. ### `BrowserAudioError` `new BrowserAudioError(code, messageKey, options?)` — `code` is one of the literal strings in `BrowserAudioErrorCode`; `messageKey` is an i18n key that the consumer's `MessageResolver` resolves at presentation time; `options` is the standard `SuaveplanErrorOptions` shape (`context`, `cause`, `traceId`, `clock`). ### `registerBrowserAudioErrorCodes()` Idempotent no-op preserved for symmetry with the `@suaveplan/error` registration ecosystem. ## Implementation Notes - `defineCodes` produces a frozen tuple-driven object; reordering entries breaks downstream type narrowing, so additions go at the **end** of the literal array. - The `category` discriminant on `BrowserAudioError` is the literal `"audio-engine-browser"`. Catch-site `instanceof BrowserAudioError` checks remain the canonical handle; the discriminant exists for structured logging only. - All codes are reachable from a real call site — exercised by `src/error-codes.test.ts` walking the registry and forcing each path.