revenuecat-troubleshoot
Diagnose and resolve RevenueCat integration issues — inspects dashboard configuration through the RevenueCat MCP, walks the SDK debug logs, and covers code-side gotchas. Use when the user says offerings are empty, products not loading, entitlement not active after purchase, paywall won't load, transactions not appearing, customer info shows no entitlements, sandbox purchase not working, or RevenueCat is broken on iOS, Android, Kotlin Multiplatform, Flutter, or React Native.
What this skill does
# revenuecat-troubleshoot: diagnose RevenueCat integration problems
Use this skill when the user reports a RevenueCat behavior that does not match expectations: empty offerings, missing products, an entitlement that does not unlock after a successful purchase, a paywall that fails to render, or sandbox transactions that never reach the dashboard.
This skill combines two angles:
1. **Code-side diagnosis** — turn on debug logging, walk a universal checklist, drop into platform specifics.
2. **Dashboard inspection** — use the RevenueCat MCP server to read the project, apps, products, entitlements, offerings, and webhooks, and offer fixes.
Work them in order. Most reports resolve before you reach the platform specifics.
## 1. Detect the platform
Inspect the working directory and pick the **first** match, from top to bottom:
1. **React Native**: `package.json` has a `react-native-purchases` entry, or `react-native` as a dependency → read `platforms/react-native.md`. If `expo` is also a dependency, note it as an Expo project.
2. **Flutter**: `pubspec.yaml` exists at the project root → read `platforms/flutter.md`.
3. **Kotlin Multiplatform**: `build.gradle.kts` contains a `kotlin { … }` multiplatform source sets block, or depends on `com.revenuecat.purchases:purchases-kmp*` → read `platforms/kmp.md`.
4. **Android (native)**: `build.gradle(.kts)` applies `com.android.application` (and is not KMP) → read `platforms/android.md`.
5. **iOS (native)**: `Package.swift`, `*.xcodeproj`, `*.xcworkspace`, or `Podfile` at the project root → read `platforms/ios.md`.
If several match (e.g. an `ios/` folder inside a Flutter project), pick the **outermost** project, the one that owns the build. If still ambiguous, ask the user which platform the bug reproduces on.
## 2. Universal code-side checklist
Walk these nine items in order. Most reports are resolved by steps 1 through 5.
1. **Turn on debug logging and reproduce.** The SDK narrates what it is doing. Roughly 80% of reports are diagnosable from the log output alone. Each platform file shows how to set `logLevel` to debug.
2. **Verify the API key platform matches the app.** iOS apps must use an `appl_…` public SDK key. Android apps must use `goog_…` (or `amzn_…` for Amazon). A mismatched key produces an authentication error on the first network call. On iOS this surfaces as an `INVALID_CREDENTIALS` error code. On Android it surfaces as `PurchasesErrorCode.InvalidCredentialsError`.
3. **Verify the bundle ID / applicationId matches the dashboard.** Open the RevenueCat dashboard → Project → Apps. The bundle identifier (iOS) or applicationId (Android) registered there must match the built app exactly, including capitalization. A mismatch causes offerings to come back empty because the app is not recognized.
4. **Verify offerings in the dashboard.** Dashboard → Products → Offerings. The offering marked "current" must have at least one package attached, and each package must reference a store product. An offering with zero packages returns an empty `availablePackages` list even though `getOfferings` succeeds.
5. **Verify store products are live.** Products must be in "Ready to Submit" on App Store Connect or "Active" on Google Play Console. A product in a draft state will not be returned by the store, even in sandbox. If the SDK logs show offerings arriving from RevenueCat but products failing to resolve, this is almost always the cause.
6. **Verify the testing account.** iOS: the device must be signed into a Sandbox Apple ID under Settings → App Store → Sandbox Account (set on iOS 14+ after the first sandbox prompt). Android: the tester's Gmail must be added to Google Play Console → Setup → License testing, and the app must be installed via the Internal Testing opt-in link, not sideloaded.
7. **Verify the network.** Corporate VPNs, captive portals, and some DNS filters silently block the RevenueCat API or the store APIs. Try a different network before digging deeper.
8. **Verify the appUserID.** If `logIn(appUserID)` was called with an ID that does not match what the user expects, entitlements appear missing because they are attached to a different RC user. Print `Purchases.shared.appUserID` (iOS) / `Purchases.sharedInstance.appUserID` (Android) and confirm it matches.
9. **Reset and retry.** Uninstall the app, re-sign into the sandbox / tester account, reinstall from the correct channel, relaunch.
## 3. Dashboard inspection via the RevenueCat MCP
Use this when steps 3, 4, or 5 above point at dashboard configuration, when the user has no working app yet, or when you need to confirm a fix landed.
**Important:** The API key may have access to multiple projects. Always call `list-projects` first. If multiple projects are returned, ask the user which to inspect.
### Phase A: gather context
1. **Symptom** — "What specifically isn't working? What error messages are you seeing? Which platform (iOS, Android, Web)?"
2. **User state** — "Is this happening for new purchases or existing subscribers? Sandbox or production?"
### Phase B: systematic diagnosis
Work through this checklist via MCP tools:
#### Check 1: Project overview
```
list-projects → ask user to select project if multiple
list-apps (with selected project_id)
```
- Verify project exists and apps are present.
#### Check 2: Products
```
list-products
```
- [ ] Products exist for each store item.
- [ ] Store identifiers match App Store Connect / Play Console exactly.
- [ ] Product types are correct (subscription vs one-time).
- [ ] Play Store: using `product_id:base_plan_id` format.
#### Check 3: Entitlements
```
list-entitlements
get-products-from-entitlement (for each entitlement)
```
- [ ] Entitlements exist for each access level.
- [ ] Products are attached to entitlements.
- [ ] No orphaned products (products not granting any entitlement).
#### Check 4: Offerings
```
list-offerings
list-packages
```
- [ ] At least one offering exists with `is_current: true`.
- [ ] Packages contain products.
- [ ] Package identifiers use standard conventions (`$rc_monthly`, etc.).
#### Check 5: Webhooks (if server-side issues suspected)
```
list-webhook-integrations
```
- [ ] Webhook URL is correct and accessible.
- [ ] Environment matches (production vs sandbox).
### Phase C: report and offer fixes
```
Diagnostic Report
=================
Project: {project_name}
Checks Passed: ✅
- Project exists and is accessible
- 2 apps configured (iOS, Android)
- 4 products found
Issues Found: ⚠️
1. CRITICAL: Product not attached to entitlement
Product: annual_premium (prod123)
Fix: Attach this product to an entitlement
2. WARNING: Offering has empty package
Offering: default / Package: $rc_annual has no products
Fix: Attach annual_premium to this package
3. INFO: No webhook configured
Optional but recommended for server-side access control
Recommended Actions:
1. Attach annual_premium to "premium" entitlement
2. Attach annual_premium to $rc_annual package
Would you like me to fix issues #1 and #2 now?
```
For each fixable issue, confirm with the user, then execute via MCP:
- `attach-products-to-entitlement`
- `attach-products-to-package`
## 4. Platform specific step
Read the platform file that matches detection. Each one lists platform specific gotchas not covered above (StoreKit configuration files, Gradle/desugaring, Metro caching, Expo prebuild, etc.).
- `platforms/ios.md`
- `platforms/android.md`
- `platforms/kmp.md`
- `platforms/flutter.md`
- `platforms/react-native.md`
## 5. Verify the fix
Do not declare the issue fixed until:
1. The log that previously showed the error now shows the expected success line (offerings returned with at least one package, purchase completed, entitlement active).
2. The dashboard reflects the change. For a purchase, check the Sandbox view on the Customers page and confirm the transaction is attached to the right `appUserID`.
3. The reproduction steps from the original report now pass.
If the user cannot Related in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.