# Error reference

Every error the SDK throws, and every error delivered in a `.failure` event, is a `TapToPayError`. The enum is `Equatable` and `Sendable` and conforms to `LocalizedError`: `errorDescription` provides an English description suitable for logs.

Match the cases you can act on and use a fallback for the rest:


```swift
do {
    let result = try await tapToPay.startTransaction(amount: 1250, currency: "USD")
    handleApproved(result)
} catch let error as TapToPayError {
    switch error {
    case .accountNotLinked:
        presentLinkFlow()
    case .readerPreparationFailed(let details):
        retryAfterPreparing(details)
    case .transactionCancelled:
        returnToCheckout()
    case .deviceBanned(let until):
        showDeviceBlocked(until: until)
    default:
        showError(error.errorDescription ?? "Something went wrong.")
    }
} catch {
    showError(error.localizedDescription)
}
```

Every case, grouped by where it occurs:

## Setup and device support

| Error | Thrown when | How to handle |
|  --- | --- | --- |
| `notSupported` | Tap to Pay on iPhone is not supported on this device (requires iPhone XS or later). | Hide Tap to Pay on iPhone entry points. Gate your UI on `FinixTapToPay.isSupported()` so users never reach this error. |
| `modelNotSupported` | Apple reports the specific device model as unsupported. | Same as `notSupported`; offer another payment method. |
| `notConfigured` | The SDK is missing valid configuration: credentials, merchant info, or `Device` ID. | Verify all `TapToPayConfiguration` fields are present and non-empty, and that the `Device` is activated. |


## Account linking

| Error | Thrown when | How to handle |
|  --- | --- | --- |
| `accountNotLinked` | An operation requires a linked Apple Account and none is linked. | Run your [link flow](/ios/tap-to-pay/account-linking), then retry. |
| `accountAlreadyLinked` | `linkAccount()` was called but the merchant already accepted the Terms and Conditions. | Treat as success and continue. Don't surface it as a failure. |
| `accountDeactivated` | The linked Apple Account has been deactivated for the merchant. | Direct the merchant to re-link; if it persists, contact Finix Support. |
| `accountLinkingCancelled` | The merchant dismissed Apple's Terms and Conditions sheet. | Return to your enablement screen and let them retry. |
| `accountLinkingCheckFailed` | The system could not check the merchant's link status. | Retry with `forceRefreshLinkStatus()`; check connectivity. |
| `accountLinkingFailed(String?)` | Linking failed. The message includes details when available. | Show a retry option and log the message. Verify iCloud sign-in and connectivity. |
| `accountLinkingRequiresiCloudSignIn` | The device is not signed in to iCloud. | Prompt the merchant to sign in to iCloud in Settings, then retry. |


## Reader preparation

| Error | Thrown when | How to handle |
|  --- | --- | --- |
| `readerPreparationFailed(String?)` | The reader could not be prepared. The message includes the underlying reason, including Apple codes 2011, 2012, and 2013. | See [Troubleshooting and support](/ios/tap-to-pay/support) for the fix for each code. Resolve the cause, then call `prepareReader()` again. |
| `emptyReaderToken` | Finix returned an empty reader token. | Usually transient. Retry, and if it persists, verify the configuration and contact Finix Support. |
| `invalidReaderToken(String?)` | The reader token was rejected as invalid. | Verify the credentials, environment, and `Device` ID all belong to the same environment. Call `refreshConfiguration()` and prepare again. |


## Transactions

| Error | Thrown when | How to handle |
|  --- | --- | --- |
| `transactionCancelled` | The Buyer, the merchant, or `cancelTransaction()` cancelled the payment. | Return to checkout. No funds moved. |
| `transactionFailed(String)` | The payment was declined or failed in processing. The message gives the reason. | Show your declined screen and offer another payment method. Log the message. |
| `backgroundRequestNotAllowed` | A reader operation was attempted while the app was in the background. | Only link, prepare, and transact while the app is in the foreground. Re-issue the call after the app returns to the foreground. |
| `deviceBanned(Date?)` | Apple has blocked this device from Tap to Pay on iPhone, optionally until the given date. | Show the date if present. Direct the merchant to another payment method and contact Finix Support. |


## Merchant, network, and tokens

| Error | Thrown when | How to handle |
|  --- | --- | --- |
| `invalidMerchant` | The merchant is invalid or unknown to Finix. | Verify `merchantId` and `merchantMid` belong to the configured environment. |
| `merchantBlocked` | The merchant is blocked from using Tap to Pay on iPhone. | Contact Finix Support. |
| `tokenFetchFailed(String)` | Authenticating with Finix to obtain a Tap to Pay on iPhone token failed. | Verify credentials, connectivity, and that the Device is activated, then retry. |
| `networkAuthenticationError` | A network-level authentication error occurred talking to Finix. | Verify API credentials match the configured environment. |
| `unknown(String)` | An unexpected error. The message contains whatever detail is available. | Log the message with a `traceId` if you have one, and contact Finix Support if reproducible. |


**Next:** [Test your integration](/ios/tap-to-pay/testing).