
rc-error-handling
Use this skill when handling errors from the RevenueCat Android SDK. Covers PurchasesError, the PurchasesErrorCode enum, the userCancelled flag on PurchasesTransactionException, and the recommended UI response per code.
- Installs
- 632
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/revenuecat/ai-toolkit --skill rc-error-handling- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads rc-error-handling automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Error Handling
Phase 1: Understand
With raw Google Play Billing you enumerate every BillingResponseCode, split them into retriable and non retriable groups, and build backoff retry logic. RevenueCat collapses this into a single type you deal with: PurchasesError.
public class PurchasesError(
val code: PurchasesErrorCode,
val underlyingErrorMessage: String? = null,
) {
val message: String // technical description, for logs
}
Key facts you rely on:
PurchasesErrorCodeis a cross platform enum with stable, readable codes.error.messageis a technical string. It belongs in logs, not in the UI.awaitPurchase()throwsPurchasesTransactionException, which adds auserCancelled: Booleanflag.- Every other
await*call (awaitOfferings,awaitGetProducts,awaitCustomerInfo,awaitRestore) throwsPurchasesException. - The SDK already retries transient billing and network failures internally. Any error that reaches you has exhausted the SDK retry budget. You do not add your own backoff loop. The only retry you implement is a user triggered "Try Again" button.
Phase 2: Plan
Before writing a catch block, decide three things:
- Which
await*call are you wrapping? That picks the exception type. - Which codes have specific handling? Everything else falls into a generic branch.
- What user facing string does each handled code map to?
Use this table to categorize PurchasesErrorCode values and pick the UX response.
| Code | Meaning | Handling |
|---|---|---|
PurchaseCancelledError | User backed out of the flow | Do nothing. userCancelled is also true. |
ProductAlreadyPurchasedError | Product already active for the user | Refresh CustomerInfo and check entitlements. |
PaymentPendingError | Purchase entered pending state | Show a pending message. Wait for UpdatedCustomerInfoListener. |
NetworkError | Request failed due to connectivity | Prompt the user to retry. |
StoreProblemError | Google Play issue | Prompt to retry or update Play Store. |
PurchaseNotAllowedError | Device or account cannot purchase | Show an explanatory message. |
IneligibleError | User not eligible for the offer | Show the base plan instead. |
Exception type decision:
| Call | Exception to catch | userCancelled available? |
|---|---|---|
awaitPurchase() | PurchasesTransactionException | Yes |
awaitRestore() | PurchasesException | No |
awaitOfferings() | PurchasesException | No |
awaitGetProducts() | PurchasesException | No |
awaitCustomerInfo() | PurchasesException | No |
Phase 3: Execute
Purchase errors
Check userCancelled first and return silently. Then branch on error.code.
try {
val result = Purchases.sharedInstance.awaitPurchase(params)
handleSuccess(result.customerInfo)
} catch (e: PurchasesTransactionException) {
if (e.userCancelled) return
when (e.error.code) {
PurchasesErrorCode.PaymentPendingError -> showPendingMessage()
PurchasesErrorCode.ProductAlreadyPurchasedError -> {
val info = Purchases.sharedInstance.awaitCustomerInfo()
handleSuccess(info)
}
PurchasesErrorCode.NetworkError -> showRetryDialog()
else -> showGenericError(userFacingMessage(e.error))
}
}
Non purchase errors
Catch PurchasesException and branch on the code. Use offline or cached fallbacks where you have them.
try {
val offerings = Purchases.sharedInstance.awaitOfferings()
displayOfferings(offerings)
} catch (e: PurchasesException) {
when (e.error.code) {
PurchasesErrorCode.NetworkError -> showOfflineFallback()
else -> logError(e.error)
}
}
Map codes to user facing strings
Keep a single mapping function. Never pass e.error.message to the UI.
fun userFacingMessage(error: PurchasesError): String = when (error.code) {
PurchasesErrorCode.PurchaseCancelledError -> ""
PurchasesErrorCode.NetworkError ->
"Please check your internet connection and try again."
PurchasesErrorCode.StoreProblemError ->
"There was a problem with Google Play. Please try again."
PurchasesErrorCode.ProductAlreadyPurchasedError ->
"You already have this subscription."
PurchasesErrorCode.PaymentPendingError ->
"Your payment is being processed. We'll notify you when it completes."
else -> "Something went wrong. Please try again."
}
Checklist
- You picked
PurchasesTransactionExceptionforawaitPurchaseandPurchasesExceptionelsewhere. - You checked
userCancelledbefore any branching onerror.code. - You handled
PaymentPendingError,ProductAlreadyPurchasedError, andNetworkErrorwith their specific flows. - You logged
error.messageand showed a mapped string fromuserFacingMessageto the user. - You did not add retry loops around SDK calls. Retries are user initiated only.
References
FAQ
What does the rc-error-handling skill do?
Use this skill when handling errors from the RevenueCat Android SDK. Covers PurchasesError, the PurchasesErrorCode enum, the userCancelled flag on PurchasesTransactionException, and the recommended UI response per code.
How do I install rc-error-handling?
Run npx skills add https://github.com/revenuecat/ai-toolkit --skill rc-error-handling in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/rc-error-handling/ (personal) or .claude/skills/rc-error-handling/ (project).
Which AI agents can use rc-error-handling?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is rc-error-handling safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains rc-error-handling?
It is published by revenuecat in revenuecat/ai-toolkit. It has 632 recorded installs.
More from revenuecat/ai-toolkit
revenuecat-paywall
revenuecat/ai-toolkit
Display a RevenueCat paywall inside an app using the RevenueCatUI SDK. Use when the user asks to add a paywall, show a RevenueCat paywall, present PaywallView, integrate RevenueCatUI, gate a premium screen with a paywall, launch PaywallActivity, call presentPaywall or presentPaywallIfNeeded, or show the dashboard configured paywall UI on iOS, Android, Kotlin Multiplatform, Flutter, or React Native. To create, edit, evaluate, or audit the dashboard paywall itself, use revenuecat-paywall-design.
integrate-revenuecat
revenuecat/ai-toolkit
End-to-end RevenueCat integration — sets up the dashboard side via the RevenueCat MCP or the rc CLI (project, app, public API key) and installs/configures the Purchases SDK in the app. Use when the user asks to add RevenueCat, hook up RevenueCat, add subscriptions or in-app purchases to an app, integrate Purchases, install the RevenueCat SDK, set up a RevenueCat API key, configure Purchases on launch, or set up a brand new RevenueCat integration on iOS, Android, Kotlin Multiplatform, Flutter, or React Native.
revenuecat-purchase-flow
revenuecat/ai-toolkit
Implement the RevenueCat purchase and restore flow. Use when the user asks to buy a package, purchase a subscription, fetch offerings, build the purchase logic behind a custom (hand-coded) paywall, handle purchase errors, detect user cancelled, or restore previous purchases on iOS, Android, Kotlin Multiplatform, Flutter, or React Native.
revenuecat-testing-setup
revenuecat/ai-toolkit
Set up a testing environment for RevenueCat purchases without charging real money. Use when the user says test RevenueCat purchases, sandbox setup, StoreKit configuration file, license tester, how do I test purchases without real money, set up sandbox account, internal testing track, or test paywall on iOS, Android, Kotlin Multiplatform, Flutter, or React Native.
create-revenuecat-project
revenuecat/ai-toolkit
Set up a complete RevenueCat project from scratch — creates apps, products, entitlements, offerings, and packages in the correct order. Use when the user wants to create a new RevenueCat project, configure in-app purchases, set up subscriptions or monetization, or bootstrap IAP infrastructure for iOS, Android, or Web.
revenuecat-troubleshoot
revenuecat/ai-toolkit
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, an SDK-gated RevenueCat feature not working, or RevenueCat is broken on iOS, Android, Kotlin Multiplatform, Flutter, or React Native. Also use when asked to check or validate the store / product setup.
Popular frontend & design skills
setup-matt-pocock-skills
mattpocock/skills
Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.
frontend-design
anthropics/skills
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
hyperframes-animation
heygen-com/hyperframes
All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.
prototype
mattpocock/skills
Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.
hyperframes-core
heygen-com/hyperframes
The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.
vercel-react-best-practices
vercel-labs/agent-skills
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.