
# Errors

**Throw what `node:fs` throws. `fsError()` builds it, `errnoOf()` puts it on the wire, and the kernel gets the code you meant.**

```ts
import { ERRNO_CODES, errnoOf, fsError, isFsError, rangeError } from "mountx";
```

## `fsError(code, options?)`

```ts
function fsError(code: ErrnoCode, options?: FsErrorOptions): FsError;
```

Builds an error byte-for-byte identical to `node:fs`'s — same `message`, `code`, negative `errno`, `syscall`, `path`, `dest`. It reaches the kernel untranslated.

```ts
throw fsError("ENOENT", { syscall: "stat", path });
throw fsError("EXDEV", { syscall: "rename", path, dest });
```

An error forwarded from a real `fs` call is already this shape — let it through unchanged.

## `isFsError(error, code?)`

```ts
function isFsError(error: unknown, code?: ErrnoCode): error is FsError;
```

The type guard, optionally narrowing on a specific code.

## `errnoOf(error)`

```ts
function errnoOf(error: unknown): number;
```

What the transports call to turn anything thrown into a wire errno. Unknown values become `EIO`, which is how the _exactly one reply per request_ rule survives a driver throwing something unexpected.

## `ERRNO_CODES`

The errno table, transcribed once, with **Linux values** — they are the numbers on the wire, not necessarily your host's. `ErrnoCode` is `keyof typeof ERRNO_CODES`.

::note
This table is transcribed in exactly one place, deliberately. The native addon reports a raw positive `errno` and lets JavaScript name it rather than carrying a second copy in another language where the two would drift.
::

## `rangeError(name, expected, value)`

Node's `ERR_OUT_OF_RANGE`, for drivers validating `read`/`write` arguments the way `node:fs` does.

## Next

- [Loopback harness](/reference/loopback) — run the driver and see what comes back out.
- [Writing a driver](/guide/drivers/custom#errors) — the same subject as prose.
