RevenueCat Invalid Receipt Error

10:00

What This Error Means

The invalid receipt error occurs when RevenueCat — or the underlying App Store (StoreKit) / Google Play Billing — rejects the purchase receipt during server-side validation. A receipt is the cryptographically-signed proof that a purchase was made. When this proof fails verification, RevenueCat cannot grant entitlements to the user.

This error surfaces most often immediately after a purchase or restore attempt, and it prevents the customer info from being updated, meaning users who paid will not receive their subscription benefits until the issue is resolved.

Important: The invalid receipt error is almost always a configuration problem, not a user error. Fixing it requires checking your app environment settings, bundle/package identifiers, and store product status.

Error Messages

You may encounter this error in several forms depending on your platform and SDK version:

text
# iOS (Swift / Objective-C)
"Invalid receipt" / Error code: 2
Error Domain=SKErrorDomain Code=0 "Invalid receipt"

# Android (Kotlin / Java)
PurchasesError(code=INVALID_RECEIPT, message="The receipt is invalid")

# Cross-platform (Flutter / React Native)
PlatformException(INVALID_RECEIPT, "The receipt is invalid", null)
RevenueCatError: INVALID_RECEIPT (2) - The receipt is invalid

Common Causes

The following are the most frequent root causes, ordered by how often they appear in practice:

  1. Sandbox receipt used in production (or vice versa)

    This is by far the most common cause. If your RevenueCat project is set up for production but you are making purchases with a sandbox Apple ID (or vice versa), the receipt environment won't match and validation will fail. This also applies when you distribute a debug build signed with your production certificate.

  2. Expired iOS receipt

    Apple's app receipts have a validity period. If a receipt is very old and not refreshed, it can be rejected. This is more common when restoring purchases on a device that hasn't opened the app in a long time.

  3. Bundle ID mismatch between app and App Store Connect

    Your app's CFBundleIdentifier (in Info.plist) must match exactly — including case — with the Bundle ID registered in App Store Connect. Even a single character difference will cause receipt validation to fail.

  4. App not published or products not active

    For both iOS and Android, the store needs to recognize the app and its products. If your iOS app has never been published or your Android app hasn't been uploaded to at least an internal testing track, receipts can't be validated server-side.

  5. StoreKit configuration file issues during development

    When using a .storekit configuration file in Xcode for local testing, mismatched product identifiers between the file and your RevenueCat dashboard will produce invalid receipt errors. Additionally, if the StoreKit config file is accidentally included in a production build, all receipts will appear invalid to Apple's servers.

Step-by-Step Fix

Step 1: Check your RevenueCat app environment (Sandbox vs. Production)

In your RevenueCat dashboard, navigate to your app settings and confirm that the environment matches what you're testing:

  • Development / TestFlight builds → should use sandbox Apple IDs
  • Production / App Store builds → should use a real Apple ID with production purchases

For Android, confirm you're testing on a build that matches the track your app is published on in Google Play Console.

Step 2: Verify bundle ID matches App Store Connect

In Xcode, open your project's Signing & Capabilities tab and confirm the Bundle Identifier matches the one in App Store Connect exactly. Check for accidental trailing spaces, different capitalisation, or extra characters.

bash
# Print bundle ID from a built .app to confirm what's actually in the binary
defaults read /path/to/YourApp.app/Info.plist CFBundleIdentifier

Step 3: For iOS development — check your StoreKit configuration file

If you're using a .storekit local configuration file in Xcode:

  1. Open the .storekit file and verify each product ID matches exactly what's in your RevenueCat Product Catalog.
  2. In your scheme settings (Edit Scheme → Run → Options), confirm "StoreKit Configuration" is set to your file for debug builds and is set to None for release/archive builds.
  3. Never ship a build with a StoreKit configuration file active — this routes all purchases through a local server that Apple cannot validate.
Tip: Open Xcode → Product → Scheme → Edit Scheme, select the Run configuration, then the Options tab. Make sure the "StoreKit Configuration" dropdown is set to None when archiving for production.

Step 4: Clear RevenueCat cache and retry

After fixing the configuration, clear the cached customer info so RevenueCat fetches a fresh receipt from the store:

swift
// Swift — invalidate cache then re-fetch customer info
Purchases.shared.invalidateCustomerInfoCache()

Purchases.shared.getCustomerInfo { customerInfo, error in
    if let error = error as? RevenueCat.ErrorCode {
        print("Error: \(error.localizedDescription)")
    } else {
        print("Active entitlements: \(customerInfo?.entitlements.active ?? [:])")
    }
}

// To check which environment RevenueCat is using:
// Look at the debug logs for "Environment: sandbox" or "Environment: production"
Purchases.logLevel = .debug
kotlin
// Kotlin — invalidate cache then re-fetch customer info
Purchases.sharedInstance.invalidateCustomerInfoCache()

Purchases.sharedInstance.getCustomerInfo(object : ReceiveCustomerInfoCallback {
    override fun onReceived(customerInfo: CustomerInfo) {
        val activeEntitlements = customerInfo.entitlements.active
        Log.d("RevenueCat", "Active entitlements: $activeEntitlements")
    }

    override fun onError(error: PurchasesError) {
        Log.e("RevenueCat", "Error code: ${error.code}, message: ${error.message}")
        // If error.code == PurchasesErrorCode.InvalidReceiptError,
        // double-check your package name and Google Play Console setup
    }
})

// Enable verbose logging to see environment details
Purchases.debugLogsEnabled = true

Step 5: Android-specific — verify Google Play service account

For Android invalid receipt errors, the most likely additional cause is a misconfigured Google Play service account in RevenueCat:

  1. In your RevenueCat dashboard, go to Project Settings → Service Credentials.
  2. Verify the Google Play service account JSON key is present and not expired.
  3. Ensure the service account has the Financial data viewer and Orders and subscriptions manager roles in Google Play Console.
  4. Confirm your applicationId in build.gradle matches the package name in RevenueCat and Google Play Console exactly.

If you're still experiencing issues after following these steps, the following guides cover the surrounding topics in more detail: