Skip to main content
Primer Checkout iOS SDK is currently in beta (v3.0.0-beta.1). The API is subject to change before the stable release.
PrimerError is the error type delivered when a payment or checkout fails. Every error carries a stable errorId for programmatic handling, a diagnosticsId to share with Primer support, and (where applicable) a recoverySuggestion describing how to recover.
public enum PrimerError: PrimerErrorProtocol {
    public var errorId: String { get }
    public var diagnosticsId: String { get }
    public var recoverySuggestion: String? { get }
    public var errorDescription: String? { get }
    public var errorUserInfo: [String: Any] { get }
    public var underlyingErrorCode: String? { get }
}
PrimerError conforms to LocalizedError and CustomNSError, so you also get localizedDescription for free and can bridge it to NSError when needed.

How errors are delivered

You never construct a PrimerError yourself. The SDK delivers it to you through one of two channels, depending on how you present checkout.
ChannelWhere the error arrives
SwiftUI statePrimerCheckoutState.failure(PrimerError) — receive the final state through the .primerCheckoutSession(session) { state in ... } modifier’s completion closure (or PrimerCheckout(clientToken:) { state in ... }) and switch on .failure.
Presenter delegatePrimerCheckoutPresenterDelegate primerCheckoutPresenterDidFailWithError(_:) for UIKit / presenter-driven integrations.
See Handle the payment result for the full success / failure / dismissed flow.

Properties

PropertyTypeDescription
errorIdStringStable, kebab-case identifier for the error category (for example "invalid-client-token", "payment-cancelled", "apple-pay-no-cards-in-wallet"). Use this for programmatic branching.
diagnosticsIdStringUnique per-occurrence diagnostics ID. Log it and provide it to Primer support when investigating an issue.
recoverySuggestionString?Suggested recovery action when one applies (for example “Check if the token you have provided is a valid token”). nil when no recovery is available (for example a user-cancelled payment).
errorDescriptionString?Human-readable description suitable for logging. Includes the errorId and diagnosticsId. Also surfaced as localizedDescription via LocalizedError.
errorUserInfo[String: Any]NSError user-info dictionary. Includes "diagnosticsId" and a "createdAt" timestamp.
underlyingErrorCodeString?An underlying provider error code when one is available. Currently populated only for NOL Pay errors; nil otherwise.
errorDescription and localizedDescription are intended for logging and diagnostics, not for display to shoppers. Show your own localized, branded messaging in the UI and reserve the SDK description for your logs.

Handling an error

Receive the checkout state through the completion closure and, in the .failure branch, log the diagnosticsId and errorId. Branch on errorId only when you need behavior specific to a category (for example treating a cancellation differently from a hard failure).
import SwiftUI
import PrimerSDK

struct CheckoutScreen: View {
    @StateObject private var session = PrimerCheckoutSession(clientToken: clientToken)

    var body: some View {
        ScrollView {
            PrimerCardForm()
        }
        .primerCheckoutSession(session) { state in
            handle(state)
        }
    }

    private func handle(_ state: PrimerCheckoutState) {
        switch state {
        case let .failure(error):
            handle(error)
        case let .success(result):
            print("Payment completed: \(result.paymentId)")
        case .dismissed, .initializing, .ready:
            break
        @unknown default:
            break
        }
    }

    private func handle(_ error: PrimerError) {
        // Always log the diagnostics ID — share it with Primer support.
        print("Checkout failed [\(error.errorId)]: \(error.localizedDescription)")
        print("Diagnostics ID: \(error.diagnosticsId)")

        switch error.errorId {
        case "payment-cancelled":
            // Shopper backed out — usually no message needed.
            break
        default:
            // Show your own branded, localized error message here.
            showRetryAlert(suggestion: error.recoverySuggestion)
        }
    }
}
For a UIKit / presenter integration, the same PrimerError arrives through the delegate:
extension CheckoutCoordinator: PrimerCheckoutPresenterDelegate {
    func primerCheckoutPresenterDidFailWithError(_ error: PrimerError) {
        print("Checkout failed [\(error.errorId)] — diagnosticsId: \(error.diagnosticsId)")
        // Present your own error UI; use error.recoverySuggestion to decide whether to offer a retry.
    }
}
When filing a support ticket, include the diagnosticsId. It lets Primer trace the exact occurrence of the failure across SDK and backend logs.

See also

PrimerCheckoutState

The checkout state that delivers .failure(PrimerError).

Handle the payment result

Handle success, failure, and dismissal end to end.

PrimerCheckoutPresenter

Receive failures through the presenter delegate.

ValidationResult

Inline field validation, distinct from checkout errors.