Troubleshooting
Common issues and how to fix them.
Enabling debug logs
The SDK provides two mechanisms for debugging.
On-screen log overlay (SwiftUI)
Add the debug config viewer to any SwiftUI view:
import SwiftUI
import Payrails
struct DebugView: View {
var body: some View {
Payrails.Debug.configViewer()
}
}This renders the parsed SDK configuration and recent log entries on screen. Requires an active session.
Console logging
The SDK writes to LogStore.shared and also calls Swift.print. To see logs in the Xcode console, ensure the scheme is not suppressing standard output.
Installation issues
pod install fails with "Unable to find a specification for Payrails/Checkout"`
- Ensure your
Podfilespecifies the correct subspec:pod 'Payrails/Checkout' - Run
pod repo updateto refresh the CocoaPods spec repos, then retry
SPM resolution fails
- Confirm the package URL is exactly
https://github.com/payrails/ios-sdk.git - Try File → Packages → Reset Package Caches in Xcode
Linker error: PayrailsCSE not found
- CocoaPods: ensure
PayrailsCSEis a transitive dependency via theCheckoutsubspec — do not remove it fromPodfile.lock - SPM: the
ios-csepackage is declared inPackage.swiftand should resolve automatically
SDK initialization issues
"Provided configuration data is invalid and cannot be parsed"
- The init payload
datafield is not valid base64-encoded JSON - Ensure your backend passes the exact string returned by the Payrails
POST /checkout/initializeendpoint without modification
"SDK has not been properly initialized"
Payrails.createCardForm()or another factory was called beforePayrails.createSession()completed- These calls trigger a
preconditionfailure if called without an active session — alwaysawaitsession creation first
Session init works in debug but fails in release
- Check that your backend call succeeds in the production environment
- Verify that the
envoption matches your backend environment (.prodvs.dev)
Card form issues
Card form appears but cannot submit — payment button stays unresponsive
- Ensure
Payrails.createCardForm()is called beforePayrails.createCardPaymentButton() - The button holds a strong reference to the form at creation time; order matters
Validation errors not shown
- Check that the card form has enough vertical space — error labels require height to render
- Use
CardFormConfig(showRequiredAsterisk: true)to make required fields explicit
Card icon not appearing
- Pass
showCardIcon: trueinCardFormConfig - Icons require the
Media.xcassetsbundle to be included. SPM bundles this automatically; CocoaPods requiresspec.resources— verify nothing is overriding it
Layout falls back to default unexpectedly (console logs "falling back to default layout")
- Your custom
CardLayoutConfigis missing required fields (.CARD_NUMBER,.CVV, and at least one expiry field) - All three are required for a valid submission
Apple Pay issues
Apple Pay button is not visible
- Check
session.isApplePayAvailable— it returnsfalseif the device has no cards or Apple Pay is not configured in the init payload - The
PKPaymentButtonhides itself whenPKPaymentAuthorizationViewController.canMakePayments()returns false
Apple Pay sheet dismisses immediately
- The merchant identifier in your app's entitlements does not match the one in the Payrails merchant configuration
- Verify the capability is enabled under Signing & Capabilities in Xcode
"incorrectPaymentSetup" error for Apple Pay
- The init payload does not include an Apple Pay payment option configuration
- Contact your Payrails integration engineer to enable Apple Pay in your merchant account
PayPal issues
PayPal button tap does nothing
- Ensure the
PayPalCheckoutSDK is properly linked (check the build phases) - The PayPal SDK requires a client ID in the init payload config; verify the payload includes it
PayPal checkout WebView dismissed with no result
- The user cancelled —
OnPayResult.cancelledByUseris delivered via the delegate callback
Payment issues
Payment results in .authorizationFailed
- This maps to
PayrailsError.authenticationError— the session token has expired - Re-initialize the session with a fresh init payload from your backend
Payment results in .failure after 3DS
- The card issuer declined the transaction post-3DS; this is not an SDK error
- Show the user an appropriate message and optionally offer another payment method
3DS challenge never appears / presentPayment(_:) not called
- Confirm that
payButton.presenter = selfis set on theCardPaymentButton - Confirm your view controller conforms to both
PaymentPresenterandPayrailsCardPaymentFormDelegateif needed
Long-polling timeout errors
PayrailsError.finalStatusNotFoundAfterLongPoll— the payment status was not confirmed within the polling window- This is typically a transient network or backend issue; prompt the user to check their payment status through your order history
Stored instruments issues
Payrails.getStoredInstruments() returns an empty array
- The init payload does not include any stored instruments for this holder reference
- Instruments with status other than
"enabled"or"created"are filtered out
StoredInstruments view renders nothing
- Same as above — the list silently renders nothing when there are no eligible instruments
- Optionally check the count before adding the view:
Payrails.getStoredInstruments().isEmpty
Getting help
- Enable debug logs and capture the output
- Reproduce the issue with
env: .devto rule out production-only configuration issues - Check the
PayrailsError.errorDescriptionfor the specific failure reason - Open a support ticket with your
executionId(fromPayrails.query(.executionId)) and the full error description
Updated about 3 hours ago