# 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 ### Checkout errors When the [checkout API](https://docs.stripe.com/api/crypto/onramp_sessions/checkout.md) returns 200 or 202 but the purchase isn’t complete, the response body includes the [CryptoOnrampSession](https://docs.stripe.com/api/crypto/onramp_sessions.md) object with `transaction_details.last_error` set. For SDK integrations, `performCheckout(onrampSessionId:authenticationContext:clientSecretProvider:)` handles payment next actions such as 3D Secure internally, so the table below only covers `last_error` values that require explicit action from your integration: | `last_error` | Description | How to handle | | ------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | `missing_kyc` | KYC verification is required. | Have the customer complete KYC in the SDK, for example, `attachKYCInfo`. Then call checkout again. | | `missing_document_verification` | Identity document verification is required. | Have the customer complete verification in the SDK, for example, `verifyIdentity`. Then call checkout again. | | `charged_with_expired_quote` | The quote expired. | Refresh the quote on your back end, then call checkout again. | | `transaction_limit_reached` | The customer exceeded their limit. | Display an error message. | | `location_not_supported` | We don’t support the customer’s location. | Show that the service isn’t available in their region. | | `transaction_failed` | A generic failure occurred. | Display a generic error message. | | `missing_consumer_wallet` | The wallet address doesn’t exist for the current customer. | Have the customer register the wallet, then call checkout again. |