In-App Purchases (IAP) are essential for monetizing your Rork app, but they're also one of the most frustrating features to set up correctly. "Products not loading," "sandbox purchases failing," "RevenueCat CustomerInfo always empty" — these are among the most common issues developers face.
Common Symptoms When IAP Isn't Working
Start by identifying which symptom matches your situation — the cause varies significantly.
- SKErrorDomain / SKErrorUnknown: Generic StoreKit error caused by configuration issues or environment problems
- Empty products array: Product ID mismatch between your code and App Store Connect
- "Cannot connect to iTunes Store": Network issues or Sandbox environment instability
- RevenueCat CustomerInfo always empty: API key misconfiguration or initialization timing issue
- "This In-App Purchase has already been bought": Sandbox account purchase history needs clearing
- Works in production but fails in Sandbox: Sandbox account configuration problem
Note which symptom you're seeing before moving on to the error analysis below.
Root Cause Analysis: 12 Common Error Patterns
Pattern 1: Product ID Mismatch
The most common cause. If the Product ID you registered in App Store Connect doesn't exactly match what's in your code — even one character difference — products will fail to load.
Pattern 2: IAP Product Status Is Not "Ready to Submit" or "Approved"
Simply registering a product in App Store Connect isn't enough. The status must be "Ready to Submit" or "Approved" for it to be usable in Sandbox testing.
Pattern 3: Sandbox Tester Account Not Configured
If your iPhone doesn't have a Sandbox tester account set up in Settings, Sandbox purchases will fail silently.
Pattern 4: Wrong RevenueCat API Key
Mixing up the public key (starts with appl_ for iOS) and the secret key, or using the Android key for iOS builds, is a surprisingly common mistake.
Pattern 5: Bundle ID Mismatch
If the Bundle ID in App Store Connect doesn't match the one in your app.json, IAP will not work — period.
Pattern 6: In-App Purchase Capability Not Enabled
The In-App Purchase capability may not be enabled in your Rork Max build configuration or Xcode project settings.
Pattern 7: Sandbox Purchase History Needs Clearing
Once you purchase a non-consumable item with a Sandbox account, trying to buy it again shows "already purchased." You need to either clear the purchase history or use a fresh Sandbox tester account.
Pattern 8: Network Issues on Test Device
Testing over VPN or on certain corporate Wi-Fi networks can block connections to the App Store servers.
Pattern 9: RevenueCat Initialized Too Late
Calling Purchases.configure() after the app has already started (e.g., inside a screen component) can cause errors on first purchase.
Pattern 10: Using expo build Instead of eas build
The legacy expo build command doesn't properly handle Capabilities and Entitlements. Always use eas build for production-ready IAP testing.
Pattern 11: Code Signing Issues
If your Provisioning Profile doesn't include the In-App Purchase Capability, you'll get errors on real device testing.
Pattern 12: Banking/Contract Not Set Up in App Store Connect
To sell paid apps or IAPs, you need to complete the Paid Apps agreement and add banking information in App Store Connect. Without this, products may not reach "Ready to Submit" status even in Sandbox.
Step-by-Step Solutions
Step 1: Verify Your IAP Products in App Store Connect
1. Log in to App Store Connect (https://appstoreconnect.apple.com)
2. Select your app → In-App Purchases → Select the product
3. Confirm the status shows "Ready to Submit" or "Approved"
4. Copy the Product ID exactly — paste it into a text file for reference
If the status shows "Missing Metadata," fill in all required fields (screenshot, description, review notes).
Step 2: Cross-Check Product IDs in Your Code
Make sure the Product IDs in your Rork-generated code exactly match what's in App Store Connect.
// ✅ Correct: Exact match with App Store Connect
const PRODUCT_IDS = {
monthly: 'com.yourcompany.yourapp.monthly', // ← copied directly, no edits
yearly: 'com.yourcompany.yourapp.yearly',
lifetime: 'com.yourcompany.yourapp.lifetime',
};
// ❌ Common mistake: subtle character differences
const PRODUCT_IDS_WRONG = {
monthly: 'com.yourcompany.yourapp.Monthly', // Capital M — will fail silently
};Step 3: Set Up Your Sandbox Tester Account
1. On iPhone: Settings → App Store → Sandbox Account
2. Enter the email and password of a Sandbox tester account
3. If you haven't created one yet:
App Store Connect → Users and Access → Sandbox → Testers → (+) Add
Important: Never use your real Apple ID for Sandbox testing. Always create dedicated Sandbox tester accounts.
Step 4: Fix RevenueCat Initialization Timing
RevenueCat must be configured as early as possible — ideally at app startup.
// App.tsx or index.js — initialize at the top level
import Purchases, { LOG_LEVEL } from 'react-native-purchases';
useEffect(() => {
const initializePurchases = async () => {
// iOS public key starts with "appl_"
await Purchases.configure({
apiKey: 'appl_xxxxxxxxxxxxxxxxxxxxxxxx',
});
// Enable debug logging during development
if (__DEV__) {
Purchases.setLogLevel(LOG_LEVEL.DEBUG);
}
// Optionally identify the user
if (userId) {
await Purchases.logIn(userId);
}
};
initializePurchases();
}, []); // Empty dependency array — run once on mount
// ❌ Don't do this: calling configure inside a screen component
// or inside a conditional renderStep 5: Debug Product Fetching
Add logging to see exactly what products are (or aren't) being returned.
import Purchases from 'react-native-purchases';
const debugOfferings = async () => {
try {
const offerings = await Purchases.getOfferings();
if (offerings.current === null) {
console.warn('No current offering — check your RevenueCat dashboard');
console.warn('Make sure an Offering is set as "Current" in RevenueCat');
return;
}
const packages = offerings.current.availablePackages;
console.log(`Found ${packages.length} packages`);
packages.forEach(pkg => {
console.log(`- ${pkg.identifier}: ${pkg.product.priceString}`);
});
} catch (error) {
console.error('Offerings fetch failed:', error.message);
// Check for "INVALID_CREDENTIALS" — means wrong API key
// Check for "NETWORK_ERROR" — check internet connection / VPN
}
};Step 6: Verify Bundle ID Consistency
# Check the bundleIdentifier in your app.json
cat /path/to/your/project/app.json | grep bundleIdentifier
# Expected output (must match App Store Connect exactly):
# "bundleIdentifier": "com.yourcompany.yourapp"If there's a mismatch, update app.json and rebuild with eas build.
Step 7: Clear Sandbox Purchase History
For non-consumable products that show "already purchased":
1. App Store Connect → Users and Access → Sandbox → Testers
2. Select the affected tester account
3. Click "Clear Purchase History"
Or simply create a new Sandbox tester account for a clean slate.
Verification: Confirming the Fix Worked
After making changes, run through this complete test flow:
1. Full Sandbox purchase flow test
① Products list loads correctly
→ Product IDs are correctly fetched from App Store Connect
② Tap the purchase button
→ Sandbox confirmation dialog appears (not an error)
③ Complete the purchase
→ Content unlocks immediately
④ Force-quit and relaunch the app
→ Purchase state is persisted (test restore functionality too)
2. Check RevenueCat dashboard
RevenueCat Dashboard → Customers → Search for your test user
→ Transactions tab should show the Sandbox purchase
3. Confirm no errors in logs
// Verbose logging for troubleshooting
Purchases.setLogLevel(LOG_LEVEL.VERBOSE);
// Watch the console for any "ERROR" or "WARNING" level messagesPrevention: Best Practices to Avoid IAP Errors
1. Set up IAP configuration before writing any code
- Register products in App Store Connect at the very start of development
- Store Product IDs in a spreadsheet and always paste — never retype — into code
2. Keep multiple Sandbox tester accounts ready
- Create at least two Sandbox accounts: one for fresh-purchase testing, one for restore testing
- Store credentials in a shared note (e.g., 1Password or Apple Notes)
3. Complete RevenueCat offering setup before coding
- Set up Offerings, Packages, and link Products in the RevenueCat dashboard first
- Don't forget to click "Save" after entering Product IDs
4. Always turn off VPN before IAP testing
- Many developers forget this step and waste hours debugging
5. Use EAS builds for realistic testing
# Build a preview profile for Sandbox IAP testing
eas build --platform ios --profile previewReal device testing with an EAS build is always more reliable than Simulator testing.
Looking back
The vast majority of Rork IAP errors come down to a handful of configuration issues: Product ID mismatches, incorrect initialization timing, Sandbox account setup problems, and API key mix-ups. Work through the checklist in this guide systematically and you'll resolve most issues within an hour.
Key takeaways:
- Always copy-paste Product IDs — never retype them
- Use a dedicated Sandbox tester account, not your real Apple ID
- Initialize RevenueCat at app startup with an empty dependency array
- Test on real devices using EAS builds, not the Simulator
- Confirm your App Store Connect product status is "Ready to Submit" before testing
For more on IAP implementation in Rork, see our Rork Max StoreKit 2 Implementation Guide and RevenueCat Subscription Monetization Guide.