---
title: Error codes
description: Every SigilError code, what it means, and when it is returned.
url: https://pr-1-10d18e06d3bf.thally.app/error-codes
---

# Error codes

Every SigilError code, what it means, and when it is returned.

Every rejection is a `SigilError` with a stable `code` property. Branch on
the code — the human-readable `message` may change between releases.

```ts
import { SigilError } from '@sigil/core';

try {
  verify(rawBody, header, secret);
} catch (error) {
  if (error instanceof SigilError) {
    console.error(error.code); // e.g. "signature_mismatch"
  }
}
```

## Code reference

| Code                         | Meaning                                                   |
| ---------------------------- | --------------------------------------------------------- |
| `header_malformed`           | Not `key=value` pairs, missing `t`, empty element, or a digest that is not 64 lower-case hex characters. |
| `header_timestamp_invalid`   | `t` is not a whole, non-negative number of seconds.       |
| `header_no_signatures`       | No `v1` element present in the header.                    |
| `header_too_many_signatures` | More than 8 `v1` elements in the header.                  |
| `signature_mismatch`         | No signature matched any supplied secret.                 |
| `timestamp_out_of_tolerance` | The timestamp is outside the tolerance window.             |
| `secret_empty`               | A supplied secret was the empty string, or no secrets were given. |
| `invalid_argument`           | A caller passed a value the API cannot use (e.g. a non-positive attempt number, or a `jitter` value outside `(0, 1]`). |
| `payload_not_json`           | The body verified successfully, but did not parse as JSON (thrown by `constructEvent`). |

## Ordering

`SIGIL_ERROR_CODES` exports this set as a read-only array in the order shown
above. The list is **append-only** — new codes are added at the end, never
inserted, because the `sigil` CLI maps each code to its own process exit code
by position.

```ts
import { SIGIL_ERROR_CODES } from '@sigil/core';

// ['header_malformed', 'header_timestamp_invalid', …, 'payload_not_json']
```

## Cross-repository contract

The [`sigil` CLI](https://github.com/fairsplitt/sigil-cli) maps each error
code to its own process exit code, one for one. Adding, removing, or
renaming a code in `@sigil/core` is a breaking change for that mapping.

## The `SigilError` class

`SigilError` extends `Error`. It has two properties:

| Property  | Type            | Description                              |
| --------- | --------------- | ---------------------------------------- |
| `code`    | `SigilErrorCode`| One of the stable codes listed above.    |
| `message` | `string`        | A human-readable explanation. May change between releases — do not branch on it. |

```ts
import { SigilError, type SigilErrorCode } from '@sigil/core';

function handleError(code: SigilErrorCode): number {
  switch (code) {
    case 'signature_mismatch':
      return 401;
    case 'timestamp_out_of_tolerance':
      return 408;
    default:
      return 400;
  }
}
```