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

# Errors and edge cases

> Every error shape the SDK flows return, what causes it, and how to handle it.

The SDK draws a line between two kinds of failure.

* **Flow-level failures** are expected outcomes. The on-chain flows (`executeSwap`, `executeTokenSale`, `authorizeWallet`) return a tagged result rather than throwing, so you handle them with a branch, not a `catch`.
* **Thrown errors** are for genuinely exceptional conditions, such as calling an authenticated method without a session.

```tsx theme={null}
const result = await coinlist.swap.executeSwap({ /* ... */ });

if (result.type === "success") {
  showReceipt(result.swapTxHash, result.outputAmount);
} else {
  handleSwapError(result.error); // result.error.step tells you where it stopped
}
```

## Wallet errors

`WalletError` is the shared vocabulary for anything the user's wallet does. It appears as the `cause` on any step that asked the wallet to sign or send.

| `type`               | Meaning                                                       | Suggested handling                                                                                          |
| -------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `user_rejected`      | The user dismissed the wallet prompt.                         | Not an error state. Return the user to the previous step so they can retry.                                 |
| `insufficient_funds` | The wallet cannot cover the amount or the gas.                | Tell the user what is short. Retrying without a top-up will fail again.                                     |
| `contract_reverted`  | The transaction reverted on-chain. Carries a `reason` string. | Surface a generic message and log `reason`. Usually a stale quote or a failed eligibility check.            |
| `timeout`            | The receipt did not arrive in time. Carries the `hash`.       | The transaction may still confirm. Link the user to an explorer with `hash` rather than prompting a resend. |
| `unknown`            | Unclassified. Carries the original `cause`.                   | Show a generic error and log `cause`.                                                                       |

If you drive a wallet yourself, `classifyWalletError(error, { hash })` turns a raw thrown wallet error into a typed `WalletError`. Pass `hash` when you are awaiting a receipt so a timeout can be reported against the right transaction.

## Swap errors

`executeSwap` returns `SwapExecutionError`, tagged by step.

| `step`              | What happened                                                              |
| ------------------- | -------------------------------------------------------------------------- |
| `status-check`      | Reading the swap contract's status failed.                                 |
| `swap-stopped`      | The swap contract is not currently accepting swaps.                        |
| `allowance-check`   | Reading the current ERC-20 allowance failed.                               |
| `approval`          | The user did not approve the ERC-20 spend. Carries a `WalletError` cause.  |
| `approval-reverted` | The approval transaction reverted on-chain.                                |
| `swap`              | The user did not sign the swap transaction. Carries a `WalletError` cause. |
| `swap-reverted`     | The swap transaction reverted on-chain.                                    |

The wallet is only asked to sign after all read-only checks pass, so a user never signs a transaction the swap would revert on for a reason the SDK could have caught first.

## Token sale errors

`executeTokenSale` returns `TokenSaleExecutionError`.

| `step`                     | What happened                                                                            |
| -------------------------- | ---------------------------------------------------------------------------------------- |
| `allowance-check`          | Reading the current ERC-20 allowance failed.                                             |
| `allowance-reset`          | The user did not sign the reset to zero. Carries a `WalletError` cause.                  |
| `allowance-reset-reverted` | The reset transaction reverted on-chain.                                                 |
| `approval`                 | The user did not approve the ERC-20 spend. Carries a `WalletError` cause.                |
| `approval-reverted`        | The approval transaction reverted on-chain.                                              |
| `participation`            | The approval succeeded but recording the participation failed. Carries `approvalTxHash`. |

<Warning>
  The `participation` step is the one to handle carefully. The user's funds are already approved on-chain, but the participation was not recorded. Keep `approvalTxHash`, surface it to the user, and reconcile rather than asking them to approve a second time.
</Warning>

### Allowance resets

The `allowance-reset` steps only occur when the wallet already holds a non-zero allowance that must be set to zero first. USDT-style tokens reject a non-zero to non-zero `approve()`, so the SDK resets before re-approving. This means those users see two wallet prompts instead of one, which is worth reflecting in your loading copy.

## Wallet authorization errors

`authorizeWallet` returns `WalletAuthorizationError`. See [Allowlist a wallet](/sdk/allowlist) for the full table and the progress phases.

## Wallet connection errors

`ConnectWalletError` carries a `code`, a `message`, and a `retryable` flag. Respect `retryable` when deciding whether to offer a retry button.

| `code`                   | Meaning                                                                                 |
| ------------------------ | --------------------------------------------------------------------------------------- |
| `not_authenticated`      | No CoinList session. Send the user through [OAuth](/sdk/oauth-authentication) first.    |
| `user_rejected`          | The user dismissed the connection prompt.                                               |
| `wallet_not_whitelisted` | The wallet is not allowlisted for this offer. See [Allowlist a wallet](/sdk/allowlist). |
| `max_wallets_reached`    | The user has already connected the maximum number of wallets for the offer.             |
| `unknown`                | Unclassified.                                                                           |

## OAuth errors

`useCompleteOAuth` fails with a `CompleteOAuthFailureReason`, which is either `complete_request_failed` or one of the client-side reasons below.

| Reason                    | Meaning                                                                                                    |
| ------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `user_canceled`           | The user declined authorization.                                                                           |
| `missing_state`           | No `state` parameter came back on the redirect.                                                            |
| `invalid_state`           | The returned `state` did not match the stored value. Treat as a possible CSRF attempt and restart sign-in. |
| `missing_code`            | No authorization code on the redirect.                                                                     |
| `missing_code_verifier`   | The stored PKCE verifier was gone, usually because storage was cleared mid-flow.                           |
| `complete_request_failed` | The code-for-token exchange against your backend failed.                                                   |

## KYC token errors

`useKycToken` fails with `not-authenticated` when there is no session, or `generic-error` for everything else.

## Thrown errors

| Error                               | When                                                                   |
| ----------------------------------- | ---------------------------------------------------------------------- |
| `NotAuthenticatedError`             | An authenticated method was called without a valid session.            |
| `CoinListClientInitializationError` | The client was used before `CoinListProvider` finished initializing.   |
| `NotImplementedError`               | A surface that is not available in the current environment was called. |

## Next steps

<CardGroup cols={2}>
  <Card title="Allowlist a wallet" icon="shield-check" href="/sdk/allowlist">
    Wallet authorization, its phases, and its error steps.
  </Card>

  <Card title="Package overview" icon="cube" href="/sdks">
    Entry points and what each one exports.
  </Card>
</CardGroup>
