# Error handling

Handle errors that occur during onramp sessions.

For general error handling, see the [Stripe error handling guide](https://docs.stripe.com/error-handling.md).

For error codes specific to the crypto onramp, see [Crypto onramp error codes](https://docs.stripe.com/crypto/onramp/embedded-components-error-codes.md).

# iOS


## SDK errors

### Configuration error

| Error                                              | Cause and fix                                                                                                                                                                             |
| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CryptoOnrampCoordinator.create()` throws an error | The `create()` factory method can fail if the underlying Link SDK fails to initialize. A common cause is an invalid publishable key set on `STPAPIClient`. Inspect the error for details. |

### Authentication error

| Error                                                      | Cause and fix                                                                                                                                                                                                                                                                                                                                                                                                                           |
| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LinkController.IntegrationError.noActiveLinkConsumer`     | The customer’s session wasn’t established or expired. Make sure that they completed authentication through `authorize` or `authenticateUserWithToken` before you call other APIs. This error can come from `authenticateUserWithToken`, `registerWalletAddress`, `attachKYCInfo`, `verifyKYCInfo`, `verifyIdentity`, `collectPaymentMethod`, and `createCryptoPaymentToken`. Re-authenticate the customer by calling `authorize` again. |
| `CryptoOnrampCoordinator.Error.seamlessSignInTokenInvalid` | `authenticateUserWithToken` throws this error when the provided token expired, was already used, or was revoked. Fall back to `authorize` to sign in the customer manually and clear any stored tokens.                                                                                                                                                                                                                                 |

### Registration error

| Error                                                    | Cause and fix                                                                                                                                                                                                                            |
| -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CryptoOnrampCoordinator.Error.linkAccountAlreadyExists` | `registerLinkUser` throws this error if the email is already associated with an existing Link account. Use `hasLinkAccount(with:)` to check before you attempt registration, or direct the customer to sign in with `authorize` instead. |
| `CryptoOnrampCoordinator.Error.invalidPhoneFormat`       | `registerLinkUser` throws this error if the phone number isn’t in E.164 format, for example, `+12125551234`. Validate the format before you call this API.                                                                               |

### Payment error

| Error                                                        | Cause and fix                                                                                                                                                                                                                                                                                                                                                         |
| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CryptoOnrampCoordinator.Error.missingCryptoCustomerID`      | `createCryptoPaymentToken` throws this error. A crypto customer ID is created during `authorize`, `authenticateUserWithToken`, or `registerLinkUser`. Make sure that one of these steps completed before you try to create a payment token.                                                                                                                           |
| `CryptoOnrampCoordinator.Error.invalidSelectedPaymentSource` | `createCryptoPaymentToken` throws this error if no payment method has been collected. `collectPaymentMethod` can also throw it if the selected method can’t be resolved internally. Make sure that `collectPaymentMethod` succeeded before you call `createCryptoPaymentToken`. If the error occurs during payment collection, retry the `collectPaymentMethod` call. |
| `CryptoOnrampCoordinator.Error.linkAccountNotVerified`       | `collectPaymentMethod` throws this error for Link payment types (`.card`, `.bankAccount`) when the Link account session isn’t in a verified state. Make sure that the customer’s authentication and verification flow completed before you collect a payment method.                                                                                                  |

### Checkout error

| Error                                | Cause and fix                                                                                                                                                                                                                           |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CheckoutError.paymentFailed`        | The underlying `PaymentIntent` reached a terminal failure state, for example, a declined card, processing error, or failed 3D Secure. Inspect the error and offer the customer an option to retry or select a different payment method. |
| `CheckoutError.missingPaymentMethod` | The `PaymentIntent` doesn’t have an associated payment method. Make sure that a payment method was collected successfully before you initiate checkout.                                                                                 |
| `CheckoutError.unexpectedError`      | A catch-all error for unexpected states during checkout. Log the surrounding context and retry the checkout.                                                                                                                            |

### Identity and KYC error

| Error                                               | Cause and fix                                                                                                                                                                                                                     |
| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CryptoOnrampCoordinator.Error.missingEphemeralKey` | `verifyIdentity` throws this error when the server responds without an ephemeral key. This usually indicates a back-end configuration issue. Make sure that the customer’s account is set up correctly for identity verification. |
| `VerifyKYCResult.updateAddress`                     | This isn’t an error. When `verifyKYCInfo` returns `.updateAddress`, show your own address form and call `verifyKYCInfo(updatedAddress:from:)` again with the new address.                                                         |

### General guidance

- All errors thrown by `CryptoOnrampCoordinator` APIs conform to `LocalizedError`. Use the `localizedDescription` property for detailed diagnostics.
- Only one `CryptoOnrampCoordinator` instance can be active at a time. Creating multiple instances can lead to undefined behavior.
- Always call `logOut()` when the customer logs out of your app to clean up SDK state and avoid stale session issues.
- When you use a test mode publishable key that contains `test`, the SDK operates against the Stripe test environment. No real transactions are processed, and no actual identity verification occurs.

## API errors

### Transaction blocked errors

Transactions can be blocked to meet compliance or risk requirements. For compliance reasons, Stripe can’t provide additional details about why a specific transaction was blocked. If you believe a transaction was blocked incorrectly, contact Stripe.

| Error code                          | Description                                                          | How to handle                                                                                         |
| ----------------------------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `crypto_onramp_transaction_blocked` | The transaction was blocked to meet compliance or risk requirements. | Show a generic error message. If you believe the transaction was blocked incorrectly, contact Stripe. |

> When testing, use the [test values](https://docs.stripe.com/crypto/onramp/embedded-components-integration-guide.md?platform=android#test-values) to avoid triggering compliance or risk checks.

### Wallet ownership verification errors

The `getWalletOwnershipChallenge(walletAddress:network:)` and `submitWalletOwnershipSignature(challengeId:signature:)` [EU Travel Rule](https://docs.stripe.com/crypto/onramp/eu-kyc-integration-guide.md?platform=ios#travel-rule-wallet-ownership) wallet ownership methods generate the following typed errors:

| Error                                  | Description                                                                                                     | How to handle                                                                   |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `WalletNotFoundError`                  | The wallet isn’t registered on the authenticated customer.                                                      | Register the wallet with `registerWalletAddress`, then request a new challenge. |
| `UnsupportedNetworkError`              | The network doesn’t support wallet ownership verification. It only supports EVM-compatible networks and Solana. | Don’t retry with this network.                                                  |
| `WalletOwnershipChallengeExpiredError` | The challenge expired.                                                                                          | Request a new challenge, collect a new signature, then submit again.            |
| `InvalidWalletOwnershipChallengeError` | The challenge is invalid or was already used.                                                                   | Request a new challenge, then submit again.                                     |
| `InvalidWalletOwnershipSignatureError` | The signature doesn’t prove control of the wallet.                                                              | Restart the full challenge and signing flow. Don’t resubmit the same signature. |

These errors map to the same underlying API error codes used by the web, React Native, and Android SDKs. Other failures—such as an unauthenticated customer or a rate-limited request—aren’t specific to wallet ownership verification and we label them as `UncategorizedError`.

