---
name: ledgerhq/errors
source: https://app.decimal.ai/s/ledgerhq-errors@2/SKILL.md
source_sha256: 9ba6ac337210
---

# Errors

Each package owns its errors in its own `src/errors.ts`, as plain native classes.
There is no shared errors lib: the former `@ledgerhq/errors` package has been removed.

## Define errors

A package groups its errors in `src/errors.ts`. Extend `Error` directly and set a
stable `name`. The `name` string is the contract — keep it stable, it is what
survives across process/serialization boundaries.

```ts
// message-only
export class FooNotFound extends Error {
  override name = "FooNotFound";
}

// with a default message
export class InvalidChallenge extends Error {
  override name = "InvalidChallenge";
  constructor() {
    super("backend returned an invalid challenge");
  }
}

// with extra fields
export class HttpError extends Error {
  override name = "HttpError";
  readonly status: number | undefined;
  constructor(message: string, status?: number) {
    super(message);
    this.status = status;
  }
}
```

Group a family under a per-package base class so callers can catch the whole set:

```ts
export class WalletAuthError extends Error {
  override name = "WalletAuthError";
}
export class WalletAuthSignatureError extends WalletAuthError {
  override name = "WalletAuthSignatureError";
  constructor(cause: unknown) {
    super("failed to sign challenge", { cause });
  }
}
```

See `libs/ledger-auth/src/errors.ts` for a full reference.

### `cause`

Use the native second argument: `super(message, { cause })`. Error `cause` was
standardized in ES2022 and is supported by modern runtimes; its TypeScript typing
(`ErrorOptions`) requires `lib: es2022.error` (i.e. `es2022`). Coin modules and
some older packages still target `es2020` — there, declare and assign manually:

```ts
export class BroadcastError extends Error {
  override name = "BroadcastError";
  cause?: unknown;
  constructor(message: string, cause?: unknown) {
    super(message);
    this.cause = cause;
  }
}
```

## Check error type: prefer `error.name`

Prefer `error.name === "FooNotFound"` over `instanceof FooNotFound`.

`instanceof` breaks once an error crosses a boundary — desktop/mobile IPC, worker
messaging, or the external `@ledgerhq/coin-module-framework` — because the object
is rebuilt and loses its prototype. The `name` string always survives.

```ts
// ✅ survives serialization
if (error instanceof Error && error.name === "FooNotFound") { … }

// ⚠️ only works in-process, before any serialization
if (error instanceof FooNotFound) { … }
```

Use `instanceof` only when you are certain the error has not crossed a boundary
(e.g. caught in the same module that threw it) and you need the typed fields.

## Where errors live

- Logic in one package → that package's `src/errors.ts`.
- Used only by an app → the app's `src/errors.ts` (`apps/ledger-live-desktop`,
  `apps/ledger-live-mobile`).
- Shared by several coin modules → `libs/ledger-wallet-framework/src/errors.ts`
  (`@ledgerhq/ledger-wallet-framework/errors`), the shared home below the coin layer.