> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rail402.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Rail402 is an x402 payment facilitator, Stellar-native Bazaar discovery layer, and agent tooling for the Stellar network. It currently targets stellar:testnet.
> The live testnet facilitator is https://facilitator.rail402.dev with endpoints /verify, /settle, /supported, /health, and /discovery/*.
> Payment amounts use 7-decimal SEP-41 integer (stroop) arithmetic. Never use floating-point math for amounts.
> Every rejection returns a machine-readable error code and a non-null human-readable reason. When explaining a failure, surface both.

# Error registry

> Every rejection carries a machine-readable code, a non-null reason, and a retryable flag. How to read them and how to handle them.

By the end of this page you will know the shape of a Rail402 rejection, the guarantee it makes, how to branch on it in code, and the notable codes you are most likely to hit.

This is the reference for [`@rail402.dev/errors`](https://www.npmjs.com/package/@rail402.dev/errors), which the facilitator, the Bazaar, the MCP server, and the SDK all share.

## The shape

Every rejection is a `{ code, reason, retryable }` object.

```ts theme={null}
{
  code: "mcp_budget_exceeded",
  reason: "The price is above the spend cap. Nothing was paid.",
  retryable: false
}
```

| Field       | Type      | Meaning                                               |
| ----------- | --------- | ----------------------------------------------------- |
| `code`      | `string`  | A stable machine-readable identifier. Branch on this. |
| `reason`    | `string`  | A human-readable explanation. Never parse it in code. |
| `retryable` | `boolean` | Whether the same call may succeed on a retry.         |

<Note>
  The guarantee: every rejection across the facilitator, the Bazaar, and the MCP server carries a non-null `reason`. There is no null, empty, or missing reason anywhere. An agent can reason about a failure without parsing prose.
</Note>

## Handling errors

`@rail402.dev/errors` (also at `@rail402.dev/sdk/errors`) exports the registry and the helpers.

```ts theme={null}
import { X402Error, isErrorCode, ERROR_REGISTRY, type ErrorCode } from "@rail402.dev/errors";
```

| Export               | What it is                                              |
| -------------------- | ------------------------------------------------------- |
| `X402Error`          | The error class carrying `{ code, reason, retryable }`. |
| `isErrorCode`        | Narrows an unknown string to a known `ErrorCode`.       |
| `ERROR_REGISTRY`     | The full map from `ErrorCode` to its registry entry.    |
| `ALL_ERROR_CODES`    | The array of every known code.                          |
| `createError`        | Builds a rejection from a registered code.              |
| `enrichUpstreamCode` | Attaches a Rail402 reason to an upstream scheme code.   |
| `ErrorCode`          | The union type of every code.                           |

The SDK's buyer functions surface the same shape as `result.error`, so you branch on `code` the same way whether you caught an `X402Error` or read a [`Result`](/reference/sdk#the-result-type).

```ts theme={null}
const result = await payAndFetch(config, url, { maxAmount: "100000" });

if (!result.ok) {
  const { code, reason, retryable } = result.error;

  if (code === "config_no_signer") {
    // fix your config, this will never succeed on retry
  } else if (retryable) {
    // a transient condition, a retry may succeed
  } else {
    console.error(code, reason);
  }
}
```

Look up any code's registered reason and retryability without triggering it:

```ts theme={null}
if (isErrorCode(someString)) {
  const entry = ERROR_REGISTRY[someString]; // { reason, retryable, ... }
}
```

## Retryable means retryable

`retryable: true` is reserved for genuinely transient conditions, such as rate limiting or a network submission failure. Everything else is `false`. Respect the flag. Retrying a non-retryable failure loops forever, and one code in particular means the money already moved, so a retry pays twice.

<Warning>
  `mcp_paid_but_resource_failed` is not retryable. The payment settled and then the resource returned an error. The funds have already moved on chain. Do not retry. See [Troubleshooting](/support/troubleshooting).
</Warning>

## Notable codes

A small slice of the registry, covering the failures you meet first. Use `ALL_ERROR_CODES` and `ERROR_REGISTRY` to enumerate the full set at runtime.

| Code                                                        | Meaning                                                                             | Retryable |
| ----------------------------------------------------------- | ----------------------------------------------------------------------------------- | --------- |
| `config_no_signer`                                          | No signing secret is configured, so nothing can be paid.                            | No        |
| `mcp_budget_required`                                       | A paying call was made without a spend cap. Nothing was paid.                       | No        |
| `mcp_budget_exceeded`                                       | The price is above the spend cap. Nothing was paid.                                 | No        |
| `invalid_exact_stellar_payload_authorization_replayed`      | The authorization was already used. Sign a fresh one.                               | No        |
| `invalid_exact_stellar_payload_missing_trustline_recipient` | The receiver has no trustline to the asset, so it cannot receive it.                | No        |
| `bazaar_mcp_resource_url_not_addressable`                   | The resource URL is `mcp://`, which has no addressable host. Use the HTTP endpoint. | No        |
| `mcp_paid_but_resource_failed`                              | The payment settled, then the resource failed. The money moved. Do not retry.       | No        |

## Next steps

<CardGroup cols={2}>
  <Card title="Troubleshooting" icon="wrench" href="/support/troubleshooting">
    Symptom, cause, and fix for the common failures.
  </Card>

  <Card title="SDK reference" icon="code" href="/reference/sdk">
    Where these codes surface in `result.error`.
  </Card>

  <Card title="FAQ" icon="circle-question" href="/support/faq">
    Answers to the questions behind many rejections.
  </Card>

  <Card title="Packages" icon="box" href="/reference/packages">
    Where the errors package fits.
  </Card>
</CardGroup>
