SDK error · code 29

customerInfoError (error code 29): Customer info error

What it means

customerInfoError (code 29 on iOS and hybrids, 28 on Android) means the SDK could not read, decode or build customer info: a cached copy has an old format, a response could not be decoded, or offline mode has no product-to-entitlement mapping. Go online once so the SDK refreshes its data, then call getCustomerInfo again.

Code

29

iOS (Swift)

ErrorCode.customerInfoError

Android (Kotlin)

PurchasesErrorCode.CustomerInfoError

Causes

Why the SDK returns customerInfoError

  • iOS: the cached customer info has an incompatible schema, for example after an SDK update (CustomerInfoManager.swift).
  • iOS: a customer info response could not be decoded (CustomerInfo.swift), or showManageSubscriptions could not fetch customer info to find the management URL.
  • Android: customer info was requested from the cache only, and the cache is empty (CustomerInfoHelper.kt).
  • Android: offline entitlements need the product-to-entitlement mapping, and the device has none cached (PurchasedProductsFetcher.kt).
  • Android numbers this code 28, while iOS and the hybrid SDKs use 29. Compare by name, not by number, when you share code across platforms.

Fix

How to fix customerInfoError

  1. 01

    Fetch customer info online once

    Open the app on a working connection and call getCustomerInfo. That refreshes the cache and the product mapping.

  2. 02

    Invalidate the cache after an SDK update

    Call invalidateCustomerInfoCache() so the SDK rebuilds from the server instead of the old copy.

  3. 03

    Check that the server serves the mapping

    Offline computation needs GET /v1/product_entitlement_mapping. Request it with your public key and confirm it returns your products.

  4. 04

    Read the underlying error

    On iOS read NSUnderlyingErrorKey. It holds the decoding or network error that caused this one.

In your app

How to handle it in code

  • One retry after a refresh is reasonable. If it fails again, the data or the server needs a fix.
  • Fall back to your last known access state for a short time, and do not block the whole app.
  • Do not grant access from the error. Grant only when customer info shows an active entitlement.
Match the errorSwift · Kotlin
// Swift
do {
  let result = try await Purchases.shared.purchase(package: package)
} catch let error as ErrorCode where error == .customerInfoError {
  // handle customer info error
}

// Kotlin
if (error.code == PurchasesErrorCode.CustomerInfoError) { /* ... */ }

On RevenueDot: RevenueDot serves the product-to-entitlement mapping at GET /v1/product_entitlement_mapping, and the SDK refreshes it when its copy is 25 hours old. With it cached, the SDK can compute access on the device while RevenueDot answers 5xx. See offline entitlements.

FAQ

customerInfoError: questions people ask

Why is customerInfoError code 28 on Android and 29 on iOS?

The Android SDK's enum numbers it 28, while the iOS enum and the hybrid enums use 29. Match on the name CustomerInfoError, not on the number.

How do I fix customerInfoError after updating the SDK?

Call invalidateCustomerInfoCache() and getCustomerInfo on a working connection. The cached copy may have an older format.

How do I check for customerInfoError in React Native and Flutter?

In React Native, compare error.code with PURCHASES_ERROR_CODE.CUSTOMER_INFO_ERROR. In Flutter, convert the PlatformException with PurchasesErrorHelper.getErrorCode(e) and compare the result with PurchasesErrorCode.customerInfoError.

Get started

Keep the RevenueCat SDK. Change the backend.

RevenueDot answers the same SDK calls with the same error codes. Start free on RevenueDot Cloud, free up to $10,000 a month in tracked revenue.

Already have an account? Sign in · Prefer your own servers? Self-host free