Use this page with AI

Copy this into your coding assistant and add your request.

Read https://openiap.dev/docs/errors and https://openiap.dev/llms.txt. Follow the reading instructions, detailed reference, and linked guides relevant to my task before making changes.
Inspect my existing project and reuse its framework and conventions. Ask me for missing product decisions. Implement the requested behavior and run the applicable checks.
Show the working result, the commands and actual test results, and any remaining limitations. Keep your explanation brief.

My request: [describe what customers should be able to do]
See an example request →

Error Codes

Error Structure

All purchase errors follow a consistent structure for easy handling. The PurchaseError shape is defined below.

swift
struct PurchaseError: Codable {
    let code: ErrorCode    // Generated error enum
    let message: String    // Human-readable message
    let productId: String? // Related product SKU (if applicable)
    let debugMessage: String? // Raw diagnostic (e.g. StoreKit error.localizedDescription)
    let responseCode: Int? // Android QueryProduct BillingResult.responseCode
    let productIds: [String]? // Android QueryProduct requested IDs
    let productType: String? // Android BillingClient product type
    let isEmptyProductList: Bool? // Android QueryProduct returned no products
    let subResponseCodeAndroid: SubResponseCodeAndroid? // Play purchase-update detail
}

Common Error Codes

User Action Errors

CodeDescriptionAction
UserCancelledUser cancelled the purchase flowNo action needed, expected behavior
UserErrorUser-related error during purchaseCheck user account status
DeferredPaymentPayment was deferred (pending family approval, etc.)Wait for payment approval
InterruptedPurchase flow was interruptedRetry the purchase

Product Errors

CodeDescriptionAction
ItemUnavailableProduct not available in storeCheck product configuration in store console
SkuNotFoundSKU not found in product listVerify SKU exists in store configuration
SkuOfferMismatchSKU offer ID mismatchCheck offer configuration for the SKU
QueryProductFailed to query product detailsCheck product IDs and retry
AlreadyOwnedItem already owned by userRestore purchases to unlock content
ItemNotOwnedItem not owned by userPurchase the item first
DuplicatePurchaseDuplicate purchase-updated event for the same token (Android)Deduplicate by purchase token and ignore duplicates
User cancellation: The canonical serialized value is user-cancelled. Some wrappers still normalize legacy E_USER_CANCELLED aliases for compatibility, but new app code should compare the generated ErrorCode.UserCancelled enum value or the user-cancelled wire value.
Android diagnostics: QueryProduct errors from openiap-google 2.1.4 and later include the Google Play Billing responseCode, debugMessage, requested productIds, requested productType, and isEmptyProductList when available. Use these diagnostics to distinguish Play Console product setup issues from transient BillingClient failures. In OpenIAP 2.3.0 / openiap-google 2.3.1, purchase-update failures also carry subResponseCodeAndroid (requires Play Billing 8.0+) when Play Billing provides a more specific reason such as insufficient funds or offer ineligibility.

Network & Service Errors

CodeDescriptionAction
NetworkErrorNetwork connection errorCheck internet connection and retry
ServiceErrorStore service errorWait and retry, check store service status
RemoteErrorRemote server errorCheck server logs, retry request
InitConnectionFailed to initialize store connectionCheck store service availability and retry
ServiceDisconnectedStore service disconnectedReconnect to the store service
ServiceTimeoutRequest reached the billing service timeout (Google Play 8.x+)Retry the call after a short delay
ConnectionClosedConnection to store service was closedReinitialize connection and retry
IapNotAvailableIn-app purchase service not availableCheck device settings and IAP availability
BillingUnavailableBilling service is unavailableCheck Google Play/App Store availability
FeatureNotSupportedRequested feature not supportedCheck device/OS version compatibility
SyncErrorSynchronization error with storeRetry synchronization

Validation Errors

CodeDescriptionAction
PurchaseVerificationFailedPurchase verification failedCheck verification logic, retry validation
PurchaseVerificationFinishedPurchase verification already completedVerification already completed, check records
PurchaseVerificationFinishFailedFailed to finish purchase verificationCheck verification state and retry
TransactionValidationFailedTransaction validation failedVerify transaction data and retry
EmptySkuListEmpty SKU list providedProvide at least one SKU to query

Error Handling Examples

Error Handling Pattern

Implement error handlers that respond appropriately to each error type:

  • User Cancellation - Silent handling, no alerts
  • Product Issues - Inform user about availability
  • Ownership Conflicts - Trigger purchase restoration
  • Network Errors - Suggest retry with backoff
  • Unknown Errors - Generic fallback message

User Cancellation

Treat user cancellation as an expected result of the purchase flow. Do not show an error alert, retry automatically, or report it as a service failure.

ts
import { ErrorCode } from 'react-native-iap';

function isUserCancellation(error: { code?: unknown }) {
  return error.code === ErrorCode.UserCancelled || error.code === 'user-cancelled';
}

Retry Strategy

Implement retry logic for transient errors:

Note: These retry strategies are automatically handled within the OpenIAP module. You don't need to implement them manually.
Error TypeCan RetryStrategy
NetworkErrorYesExponential backoff (2^n seconds)
ServiceErrorYesLinear backoff (n * 5 seconds)
RemoteErrorYesFixed delay (10 seconds)
ConnectionClosedYesReinitialize and retry
SyncErrorYesExponential backoff
UserCancelledNoDo not retry
AlreadyOwnedNoRestore instead
DeferredPaymentNoWait for approval
NotPreparedNoInitialize connection first

Platform-Specific Error Handling

iOS Error Codes

Native CodeMapped ErrorDescription
0UnknownUnknown error
1UserCancelledUser cancelled transaction
2NetworkErrorNetwork unavailable
3ItemUnavailableProduct not available
4ServiceErrorApp Store service error
5PurchaseVerificationFailedPurchase verification failed
6AlreadyOwnedProduct already purchased

ErrorCode Enum (Unified)

Complete list of error codes that can be returned by the IAP library.

swift
enum OpenIapError: Error {
    case unknown
    case userCancelled
    case userError
    case itemUnavailable
    case remoteError
    case networkError
    case serviceError
    case purchaseVerificationFailed
    case purchaseVerificationFinished
    case purchaseVerificationFinishFailed
    case notPrepared
    case notEnded
    case alreadyOwned
    case developerError
    case billingResponseJsonParseError
    case deferredPayment
    case interrupted
    case iapNotAvailable
    case purchaseError
    case syncError
    case transactionValidationFailed
    case activityUnavailable
    case alreadyPrepared
    case pending
    case connectionClosed
    case initConnection
    case serviceDisconnected
    case serviceTimeout
    case queryProduct
    case skuNotFound
    case skuOfferMismatch
    case itemNotOwned
    case billingUnavailable
    case featureNotSupported
    case emptySkuList
    case duplicatePurchase
}

Testing Error Scenarios

Testing Error Scenarios

iOS Sandbox Testing

Test AccountSimulated Error
test.purchase.failed@example.comPurchaseVerificationFailed
test.purchase.cancelled@example.comUserCancelled
test.purchase.unavailable@example.comItemUnavailable

Android Testing Methods

Test MethodDescription
License TestingAdd test accounts in Google Play Console for real purchases without charges
Internal Testing TrackDeploy to internal testers for production-like testing
Closed TestingTest with limited group of users before production release
Test Cards (Sandbox)Use test payment methods configured in Play Console

⚠️ Important: Static test product IDs like android.test.purchased are deprecated and no longer work. Use real product IDs with test accounts instead. See Releases page for details →

Development Testing

For development testing, consider implementing mock error generators that can simulate various error conditions without requiring actual purchases. This allows you to:

  • Test error handling UI flows
  • Verify analytics tracking
  • Validate retry logic
  • Ensure proper error recovery