Chapter 8: Error Handling
Handling billing errors directly means dealing with every BillingResponseCode, categorizing them into retriable and non-retriable groups, and building an exponential backoff retry system. Different response codes require different actions: some require reconnection, some require user intervention, some should be silently ignored.
With RevenueCat, you handle one error type: PurchasesError. The SDK has already absorbed the BillingResponseCode layer.
PurchasesError
Every failure in the RevenueCat SDK surfaces as a PurchasesError:
PurchasesErrorCode is a cross-platform enum with human-readable codes. The message property on PurchasesError gives a description suitable for logging (not for showing directly to users).
The Error Codes You Handle in Practice
Most of your error handling code deals with these codes:
Handling Purchase Errors
PurchasesTransactionException is a subtype of PurchasesException that adds userCancelled: Boolean. Use it for awaitPurchase() only. For awaitRestore(), catch PurchasesException (the base class), restore does not produce a PurchasesTransactionException.
Handling Non-Purchase Errors
For awaitOfferings(), awaitGetProducts(), and awaitCustomerInfo(), catch PurchasesException:
Retry Logic
You do not write retry logic for transient errors. The SDK retries BillingClient operations internally with backoff for SERVICE_UNAVAILABLE and ERROR response codes. The errors that surface to your code are already past the retry budget.
For NetworkError on RevenueCat API calls (the calls that post purchases or fetch CustomerInfo), the SDK also retries internally. A NetworkError reaching your catch block means retries were exhausted.
The only retries you implement are user-initiated: a "Try Again" button that re-calls the relevant SDK method.
User-Facing Error Messages
Do not show e.error.message to users, it is a technical description. Map to user-facing strings: