VoidhashDocs
DevelopersHelp centerGuidesAPI reference
Dashboard
Get started
Introduction
Quickstart
How Voidhash works
Glossary
Versions and releases
Concepts
Teams, projects and environments
API keys
Products and perks
Offers
Subscription lifecycle
People and identity
Events
Features
Paywalls in your app
Feature flags and A/B tests
Paywall components
Push notifications
Ad attribution in your app
Client SDKs
React Native
Swift
Kotlin
Web
Your backend
Node.js
PHP
Go
Rust
Other languages
Payment sources
Forward store notifications
Developer tools
CLI
MCP server
Query analytics with VoidQL
React Native SDK
React Native quickstart
Display a paywall
Make and restore purchases
Check access
Identify users
Evaluate feature flags
Capture analytics
Track screens
Development mode
React Native SDK reference
Errors
Troubleshooting

Troubleshooting

Fix common React Native SDK problems, organized by symptom.

Find your symptom below; each section lists causes in the order to check them. Set debug: true and an onDiagnostic handler while you investigate: most problems show up there first. See Diagnostics.

FLOW_RENDERER_MISSING

The build doesn't include the paywall renderer. The published packages don't ship it yet, so follow Add the paywall renderer and check:

  1. node_modules/@voidhash/ios-ui contains Artifacts/VoidhashUIEngine.xcframework, and node_modules/@voidhash/android/ui/src/main/jniLibs contains libvoidhash_ui.so for each ABI. Reinstalling dependencies removes them.
  2. In Expo, the plugin is registered as ["@voidhash/react-native", { "renderer": true }], not the bare string. In a bare app, the Podfile has the VoidhashUI pod and android/gradle.properties has Voidhash_renderer=true.
  3. You ran npx expo prebuild and rebuilt the native app. A JavaScript reload or an over-the-air update doesn't add native code.

The paywall doesn't appear

Check the failed result's error.code:

  • FLOW_NOT_ASSIGNED: nothing is shown at the location. Check the slug you pass to presentFlow, that the location isn't archived, and that a paywall is deployed and shown there. See Paywall locations. If it is, the deployed build may need a newer SDK.
  • FLOW_UNAVAILABLE: the device has never loaded this location and is offline.
  • FLOW_UNSUPPORTED_PACKAGE: update the SDK.
  • FLOW_PRESENTATION_FAILED: present from a screen that is mounted and visible.

A paywall you just deployed can take up to about an hour to replace a cached one on a device that showed the location before. Reinstall the app to test a deploy right away.

Products are empty

useProducts().data.get(slug) returns undefined, or a paywall shows no prices.

  1. In a debug build with dev: true, check that you use the test key (vh_pk_test_...) and that Enable simulated purchases is on in Settings → General.
  2. Otherwise, check that the App Store or Google Play is connected and the product is mapped to its store product ID. See Products and perks.
  3. Check the product in the store: on the App Store, the Paid Applications Agreement is active and the product is ready to submit; on Google Play, the app is published to a testing track and the product is active.
  4. Test on a real device signed in to a sandbox or license tester account; see Test purchases (Help center).

A purchase doesn't unlock the perk

  1. Check the purchase result. deferred means the receipt is still queued for Voidhash; access arrives once it's accepted. pending waits for approval.
  2. Check that the product unlocks the perk you check, by slug, in Products → Products.
  3. Watch onDiagnostic for TRANSACTION_REJECTED: Voidhash refused the receipt, usually because the store isn't connected for this bundle ID or package name.
  4. Check the key: a TestFlight or Play test build on the test key doesn't see production perks, and with the store-sandbox-unlocks-production setting off, sandbox purchases don't unlock production apps. See Environments.
  5. In observer mode, check that you report the purchase with reportTransaction.

Expo Go isn't supported

The SDK ships native modules, which Expo Go can't load: initialization fails with FAILED_TO_INITIALIZE_VOIDHASH_CLIENT. Use a development build (npx expo run:ios, npx expo run:android or EAS). The same error appears when an over-the-air update ships the SDK's JavaScript to a binary built without it; rebuild the binary.

Native build fails

  • iOS pod install can't find VoidhashCore: in a bare app, add the Podfile lines from the quickstart. In Expo, the plugin needs a use_expo_modules! or use_native_modules! line in the Podfile.
  • Errors mentioning Nitro: every Nitro module in the app must use the same 0.37.x version.
  • Android billing errors at runtime: another billing library in the app still uses APIs removed in Google Play Billing 8. Upgrade it. The SDK needs compileSdkVersion 35.
  • effect errors: install exactly effect@4.0.7.

Sandbox purchases

  • TestFlight and Play test-track builds use the production key; their purchases are recorded in the sandbox environment and appear under Sandbox in Studio.
  • The App Store sandbox renews subscriptions on an accelerated schedule; the renewals arrive as regular renewals.
  • Simulated purchases from development mode appear under Test. Move them through renewals and refunds with voidhash sandbox; see Development mode.

Events don't show up

  1. Check analytics consent: with "denied" or "pending", nothing is recorded and ANALYTICS_CONSENT_DENIED is reported once.
  2. Check the environment in Studio: debug builds on the test key send test events, shown under Test.
  3. Check Settings → Events: a turned-off built-in event or a blocked custom event isn't stored.
  4. Events are sent every 5 seconds or 20 events. Call flush() and check pending and lastError.
  5. AUTHENTICATION_FAILED in onDiagnostic means the publishable key was rejected.

See Check your data for what Studio received.

Access is wrong after sign-in

  • Call identify() only after your auth library has restored the session, and signOut() only for an identified user. Calling signOut() for an anonymous person leaves their purchases behind.
  • PERSON_WRITE_REJECTED after identify() means the anonymous ID already belonged to another identified user, so its purchases weren't merged. A Restore button moves them according to the project's paid access sharing setting.

Next steps

  • Errors
  • Test purchases (Help center)
  • Troubleshooting across platforms

Something wrong or missing on this page? Tell us by email or on Discord.

PreviousErrorsNextSwift SDK

On this page

FLOW_RENDERER_MISSINGThe paywall doesn't appearProducts are emptyA purchase doesn't unlock the perkExpo Go isn't supportedNative build failsSandbox purchasesEvents don't show upAccess is wrong after sign-inNext steps