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

# Error Handling

> How to handle errors, retries, and edge cases.

## HTTP status codes

| Code  | Meaning          | When                                                |
| ----- | ---------------- | --------------------------------------------------- |
| `200` | Success          | GET requests, idempotent retries                    |
| `201` | Created          | POST that creates a resource                        |
| `400` | Bad request      | Malformed JSON, missing required fields             |
| `401` | Unauthorized     | Invalid or expired JWT                              |
| `403` | Forbidden        | Insufficient scopes/permissions                     |
| `404` | Not found        | Resource does not exist or not in your environment  |
| `409` | Conflict         | Duplicate idempotency key, invalid state transition |
| `422` | Validation error | Valid JSON but business rule violated               |

## Error response format

All errors return a consistent structure:

```json theme={null}
{
  "detail": "Human-readable error message"
}
```

For validation errors (422):

```json theme={null}
{
  "detail": [
    {
      "loc": ["body", "parties", 0, "role"],
      "msg": "Field required",
      "type": "missing"
    }
  ]
}
```

## Idempotency

Instruction submission is idempotent via `idempotency_key`. If you send the same key:

* First call: creates the instruction (201)
* Subsequent calls: returns the existing instruction (200)

This makes all submission calls safe to retry on network errors.

## Retrying failed requests

| Scenario           | Retry? | Strategy                                |
| ------------------ | ------ | --------------------------------------- |
| Network timeout    | Yes    | Retry with same idempotency key         |
| 5xx server error   | Yes    | Exponential backoff                     |
| 401 Unauthorized   | Yes    | Refresh token first, then retry         |
| 400/422 Validation | No     | Fix the request                         |
| 409 Conflict       | No     | Check current state, decide next action |
| 404 Not Found      | No     | Verify the resource ID                  |

## Settlement-specific errors

### Compliance decision on wrong state

```json theme={null}
// 409
{"detail": "Settlement is not awaiting a compliance decision"}
```

The settlement has already advanced past the compliance check. Query the current state to see where it is.

### Instruction not cancellable

```json theme={null}
// 409
{"detail": "Instruction is not cancellable"}
```

Only instructions with `status: pending_match` can be cancelled. Instructions that have already been matched, expired, or cancelled cannot be changed.

### Template validation failures

```json theme={null}
// 422
{"detail": "Missing required role: buyer"}
```

The settlement instruction does not satisfy the template's `required_roles` or `required_leg_types`.

## On-chain error handling

When the KeystoneSettlement contract rejects an operation (e.g. the compliance gate is closed at execution time, or a deposit fails the commitment check), the transaction reverts and the settlement remains in its current state. A closed gate never blocks deposits - the settlement simply stays registered until attestation lands.

If the settlement reaches its `timeout_at` deadline, any depositor (or the operator) can call `claimTimeout()` on the KeystoneSettlement contract, then reclaim deposits per leg via `claimRefund()`. Neither path can be paused or depends on KeyStone being up - every party with funds at stake can recover them itself.

## Webhook error handling

If your webhook endpoint returns a non-2xx response:

1. KeyStone retries with exponential backoff
2. Failed deliveries are logged in the delivery log
3. The settlement continues regardless (webhooks are notifications, not blocking)

Always handle webhooks idempotently - you may receive the same event more than once.
