# stream-error _(no submodules)_ ## Purpose Defines the structured error hierarchy for the `@suaveplan/streams` package. Every runtime error emitted by stream operations is an instance of `StreamError` (which extends `SuaveplanError`) and carries a stable, dot-namespaced error code from the `STREAM.*` registry. This design means callers can narrow errors programmatically — `error.code === STREAM_CODES.ABORTED` — without string-matching unstructured messages, and ensures that OTel integrations, log pipelines, and dead-letter queues can route stream errors reliably. The codes are registered once via `defineCodes("STREAM", [...])` and reused across every throw site. Codes are intentionally coarse-grained: they represent the semantic category of failure, not the specific call stack location, so they remain stable across refactors. ## Features - Six concrete error subclasses covering all stream failure modes - Stable `STREAM.*` error code registry via `defineCodes` - Exported `StreamErrorCode` union type for exhaustive switch statements - Each subclass propagates `cause` when it is an `Error` instance - All classes extend `StreamError` which extends `SuaveplanError`, compatible with the project error wire format ## Usage: Basic Example ```ts import { StreamAbortedError, STREAM_CODES } from "@suaveplan/streams/errors/stream-error"; function checkAborted(signal?: AbortSignal): void { if (signal?.aborted) { throw new StreamAbortedError({ cause: signal.reason }); } } try { checkAborted(AbortSignal.abort()); } catch (err) { if (err instanceof StreamAbortedError) { console.log(err.code); // "STREAM.ABORTED" } } ``` ## Usage: Advanced Example ```ts import { StreamTransformFailedError, StreamClosedError, StreamReadFailedError, STREAM_CODES, } from "@suaveplan/streams/errors/stream-error"; function handleStreamError(err: unknown): never { if (!(err instanceof Error)) { throw new StreamReadFailedError({ message: "Unknown read failure" }); } switch ((err as { code?: string }).code) { case STREAM_CODES.CLOSED: throw new StreamClosedError({ message: "Cannot read from closed stream" }); case STREAM_CODES.TRANSFORM_FAILED: throw new StreamTransformFailedError({ cause: err }); default: throw new StreamReadFailedError({ cause: err }); } } ``` ## API Reference ### `STREAM_CODES` `Record` — the stable code map. Keys: `ABORTED`, `BACKPRESSURE_EXCEEDED`, `CHUNK_INVALID`, `PIPE_FAILED`, `TRANSFORM_FAILED`, `SOURCE_EXHAUSTED`, `READ_FAILED`, `WRITE_FAILED`, `CLOSED`. Values are dot-namespaced strings like `"STREAM.ABORTED"`. ### `StreamError` Base class. Extends `SuaveplanError`. All concrete subclasses inherit from this. ### `StreamAbortedError` Thrown when an `AbortSignal` fires mid-operation. Constructor: `{ cause?: unknown; message?: string }`. ### `StreamTransformFailedError` Thrown when a user-supplied transform function throws. Constructor: `{ cause?: unknown; message?: string }`. ### `StreamClosedError` Thrown when an operation is attempted on a closed stream. Constructor: `{ message?: string }`. ### `StreamReadFailedError` Thrown on unrecoverable read failures. Constructor: `{ cause?: unknown; message?: string }`. ### `StreamWriteFailedError` Thrown on unrecoverable write failures. Constructor: `{ cause?: unknown; message?: string }`. ### `StreamPipeFailedError` Thrown when a pipe or pipeline composition fails. Constructor: `{ cause?: unknown; message?: string }`. ## Implementation Notes `defineCodes` generates stable string codes by joining the namespace prefix and the key with a dot. The generated values are frozen at module-init time and never change, which means error codes survive across serialization round-trips (they appear verbatim in JSON error envelopes). Cause propagation is conditional: we only set `cause` when the original value `instanceof Error` to avoid accidentally serializing non-Error objects into the error chain.