# `error-codes.ts` — `AUDIO_IR_LOADER.*` registry _(no submodules)_ ## Purpose This module is the single source of truth for every error code raised by `@suaveplan/audio-ir-loader`. It uses `defineCodes` from `@suaveplan/error` to register an immutable, byte-stable mapping of short keys (`MANIFEST_MISMATCH`) to fully-qualified strings (`AUDIO_IR_LOADER.MANIFEST_MISMATCH`). It also declares the `AudioIrLoaderError` class, which exposes every dimension an operator might filter on (`id`, `extension`, `field`, `manifestValue`, `decodedValue`, `maxBytes`, `decodedBytes`, `errors`) as typed read-only properties so dashboards and routing layers never have to parse message text to know what happened. ## Features - Six codes — `DECODER_UNAVAILABLE`, `MANIFEST_MISMATCH`, `ABORTED`, `CACHE_OVERFLOW`, `DECODE_FAILED`, `RESOLVE_FAILED`. - Frozen registry object — `Object.isFrozen(AUDIO_IR_LOADER_CODES)` is true. - Typed error class with discriminants pre-typed on the class. - Aggregate `errors[]` for the `DECODE_FAILED` partial-failure path from `preload`. ## Usage: Basic ```ts import { AUDIO_IR_LOADER_CODES, AudioIrLoaderError, } from "@suaveplan/audio-ir-loader"; throw new AudioIrLoaderError( AUDIO_IR_LOADER_CODES.DECODER_UNAVAILABLE, "no decoder registered for .flac", { id: "club-club1", extension: "flac" } ); ``` ## Usage: Advanced The aggregate `errors` discriminant powers the `preload` partial-failure contract: ```ts import { AudioIrLoaderError, AUDIO_IR_LOADER_CODES } from "@suaveplan/audio-ir-loader"; try { await loader.preload(["a", "b", "c"]); } catch (err) { if ( err instanceof AudioIrLoaderError && err.code === AUDIO_IR_LOADER_CODES.DECODE_FAILED ) { for (const { id, error } of err.errors ?? []) { console.error(`load ${id} failed:`, error.code); } } } ``` Operators routing on the structured discriminants can ship dashboards that break down failures by `extension` for `DECODER_UNAVAILABLE`, by `field` for `MANIFEST_MISMATCH`, and by the size pair (`maxBytes` / `decodedBytes`) for `CACHE_OVERFLOW`, with zero message-text regexes. ## API Reference ### `AUDIO_IR_LOADER_CODES` Frozen `Readonly">>` with keys `DECODER_UNAVAILABLE`, `MANIFEST_MISMATCH`, `ABORTED`, `CACHE_OVERFLOW`, `DECODE_FAILED`, `RESOLVE_FAILED`. ### `AudioIrLoaderError extends SuaveplanError` Constructor: `(code, message, options?)`. Discriminants on the instance: `id`, `extension`, `field`, `manifestValue`, `decodedValue`, `maxBytes`, `decodedBytes`, `errors`. `name === "AudioIrLoaderError"`. ### `AudioIrLoaderErrorOptions` Extends `SuaveplanErrorOptions` with the seven optional discriminants listed on the class plus `errors: readonly AggregatedLoadFailure[]`. ### `AggregatedLoadFailure` `{ id: string; error: SuaveplanError }` — one entry per failed id in a `preload` aggregate. ## Implementation Notes `defineCodes` returns a frozen object; the registry guarantees byte-stable code strings across builds. The discriminants on `AudioIrLoaderError` are declared as `T | undefined` rather than via `exactOptionalPropertyTypes` gymnastics so callers reading the property always get an unambiguous "absent" sentinel. Every code in this registry is exercised by a real call site under test (see `error-codes.test.ts`) — the exhaustion test guarantees we cannot register a code that has no production thrower.