# 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. Establish a session through `registerLinkUser` or `authorize` before calling APIs that require it. Apple Pay collection can run before a session is established. This error can come from `registerWalletAddress`, `attachKYCInfo`, `verifyKYCInfo`, `verifyIdentity`, `collectPaymentMethod`, and `createCryptoPaymentToken`. Re-authenticate the customer by calling `authorize` again. |

### 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` 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`, `.cardAndBankAccount`) 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.                                                                           |

### Platform Pay account change 

For Apple Pay collected before registration or authentication, while the coordinator has no crypto customer ID, `createCryptoPaymentToken` revalidates the onramp merchant of record. It throws `PaymentMethodKYCRegionChangedError` with code `payment_method_kyc_region_changed` if the merchant of record used during collection differs from the one required by the customer’s KYC region.

Keep the authenticated coordinator, present Apple Pay again, and retry token creation only after collection succeeds. If the customer cancels, stop instead of retrying with the previous selection. `createCryptoPaymentToken` doesn’t present UI automatically. An accurate `countryHint` reduces the likelihood of this error but doesn’t override an established KYC region.

In [iOS SDK 26.14.0](https://github.com/stripe/stripe-ios/releases#release-26.14.0), this revalidation doesn’t apply when a crypto customer ID already exists at collection time. If you register or authenticate, collect Apple Pay, and then submit KYC that changes the customer’s region, token creation can instead fail with the API error `crypto_onramp_invalid_parameter` for `payment_method`. For this sequence, establish the customer’s KYC region before collecting Apple Pay. Don’t treat every `crypto_onramp_invalid_parameter` error as a region change; it can also indicate other invalid parameters.

### 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

- Use `error.localizedDescription` for diagnostics. Errors from your checkout callback can retain their original type.
- 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 sandbox publishable key, which starts with `pk_test_`, the SDK operates against your sandbox. 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. Otherwise-unmapped Stripe API errors become `UncategorizedError`. Local SDK errors and errors thrown by your app can retain their original type.

