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

# Error Handling

> Map Kimia program errors to user-friendly messages and recovery paths.

Anchor program errors surface as numeric codes in transaction logs. Kimia's
Codama-generated clients turn them into typed enums, but you still need a
strategy for:

* Detecting which program the error came from
* Mapping it to a user-facing message
* Deciding between retry, prompt, or give-up

## Shape of an Anchor error in logs

```
Program CU3A8MLxrJsz4CiahcduqubCA2WrniiVS4jdovxyyjR6 invoke [1]
Program log: Instruction: RecordStep3
Program log: AnchorError occurred. Error Code: TargetRateNotAchievable. Error Number: 6001. Error Message: Target rate not achievable.
Program CU3A8MLxrJsz4CiahcduqubCA2WrniiVS4jdovxyyjR6 consumed 22345 of 200000 compute units
```

Kimia clients parse the `Error Number` and the emitting program ID to route
errors to the right enum.

## Parsing helper

```ts theme={null}
import {
  isKimiaPerpError,
  KIMIA_PERP_ERROR__STALE_ORACLE,
  KIMIA_PERP_ERROR__INSUFFICIENT_FREE_COLLATERAL,
  KIMIA_PERP_ERROR__SLIPPAGE_EXCEEDED,
} from '@/app/generated/perp/errors';

export function toUserMessage(err: unknown): string {
  if (isKimiaPerpError(err, KIMIA_PERP_ERROR__STALE_ORACLE)) {
    return 'Price feed is stale. Please try again.';
  }
  if (isKimiaPerpError(err, KIMIA_PERP_ERROR__INSUFFICIENT_FREE_COLLATERAL)) {
    return 'Not enough free collateral. Cancel open orders or deposit more.';
  }
  if (isKimiaPerpError(err, KIMIA_PERP_ERROR__SLIPPAGE_EXCEEDED)) {
    return 'Price moved too much before filling. Raise max slippage or reduce size.';
  }
  // ... fall-through cases
  return 'Transaction failed. See logs for details.';
}
```

See `frontend/app/lib/errors.ts` for the full mapping the reference UI uses.

## Error categories by program

### kimia-perp (6000..6199)

| Bucket           | Codes     | Typical recovery                                                      |
| ---------------- | --------- | --------------------------------------------------------------------- |
| Oracle           | 6000-6002 | Retry (auto-reposts Hermes update)                                    |
| Market lifecycle | 6010-6012 | Wait for admin / switch market                                        |
| Margin           | 6020-6022 | Deposit more collateral, reduce size                                  |
| Position         | 6030-6033 | Fix size / direction                                                  |
| Funding          | 6040-6041 | Wait for the funding period to elapse                                 |
| Liquidation      | 6050-6051 | Account not liquidatable (healthy)                                    |
| Deposit/withdraw | 6060-6061 | Amount > 0; enough balance                                            |
| Math             | 6070      | Reduce size; hits u128 intermediates                                  |
| Auth             | 6080-6081 | Use authority wallet; delegate can't withdraw                         |
| Slippage         | 6090      | Raise `max_slippage_bps`                                              |
| Insurance        | 6100      | Bad debt; market paused until admin                                   |
| Orderbook        | 6110-6117 | Book full, order not found, crossing post-only, market-order slippage |
| Spot pool        | 6130-6133 | Pool paused, insufficient liquidity, swap slippage, zero amount       |

### delta-vault

| Error                     | Recovery                                                   |
| ------------------------- | ---------------------------------------------------------- |
| `VaultNotActive`          | Wait for admin resume                                      |
| `VaultNotPaused`          | Admin-only paths require paused state                      |
| `PerpsUserAccountNotInit` | Call `init_perps_user_account` once                        |
| `NavCorrupted`            | Admin `admin_resync_nav`; shouldn't happen in normal ops   |
| `DeltaExceedsThreshold`   | Spot/perp legs have diverged more than the rebalance cap   |
| `VaultNotMigrated`        | Admin must run `admin_setup_spot_leg` before first deposit |

### split-engine

| Error                     | Recovery                                          |
| ------------------------- | ------------------------------------------------- |
| `NotMatured`              | Wait until `maturity` timestamp                   |
| `AlreadyMatured`          | Use `redeem_pt` instead of `deposit`              |
| `NoYieldToClaim`          | Nothing to claim yet; call `update_rewards` first |
| `SupplyInvariantViolated` | Protocol bug, do not ignore; report it            |
| `ZeroDeposit`             | Deposit amount must be greater than zero          |

### yield-amm

| Error                      | Recovery                                                   |
| -------------------------- | ---------------------------------------------------------- |
| `SwapDisabledNearMaturity` | Too close to maturity; just `redeem_pt`                    |
| `SlippageExceeded`         | Raise `min_amount_out` tolerance                           |
| `InsufficientLiquidity`    | Larger size than pool supports                             |
| `EmptyPool`                | Pool hasn't been seeded yet                                |
| `InvariantViolated`        | Post-swap invariant check failed — retry with smaller size |

### intent-router

| Error                     | Recovery                                                                 |
| ------------------------- | ------------------------------------------------------------------------ |
| `InvalidSessionState`     | Step must follow Created → Step1 → Step2 → Step3                         |
| `TargetRateNotAchievable` | Lower target, or wait for AMM to recover                                 |
| `TargetRateNotAchieved`   | Achieved rate was below target at step 3; session stays at Step2Complete |
| `PtBalanceMismatch`       | Step 2 can't account for expected PT                                     |
| `NegativeDiscount`        | PT redeemed for more than face value                                     |
| `InvalidDuration`         | Session duration must be greater than zero                               |

## Retry policy

**Auto-retryable errors:**

* `StaleOracle`, re-fetch Hermes, rebuild tx, retry.
* RPC transient errors (connection, blockhash not found), exponential
  backoff.

**User-prompt errors:**

* `SlippageExceeded`, ask the user to raise slippage tolerance.
* `InsufficientFreeCollateral`, prompt a deposit or cancel-orders flow.

**Give up / show error:**

* `MarketNotActive`, `VaultNotActive`, nothing the user can do until admin.
* Math errors (`MathOverflow`), your input was too large; don't retry.

## Logging raw errors

For unknown or unmapped errors, log:

* Transaction signature
* Program logs (`tx.meta.logMessages`)
* Which instruction in the tx failed (Anchor logs `Instruction: X`)

Include these three artefacts in any bug report.
