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
Kotlin SDK
Kotlin quickstart
Display a paywall
Make and restore purchases
Check access
Identify users
Evaluate feature flags
Capture analytics
Track screens
Development mode
Kotlin SDK reference
Errors
Diagnostic codes
Troubleshooting

Troubleshooting

Find the cause and fix for common Kotlin SDK problems, by symptom.

Find your symptom below for its likely causes and fixes. Turn on debug = true to see SDK warnings in logcat under the tag Voidhash, and log diagnostics with onDiagnostic: most of these problems show up there first.

Gradle can't resolve the SDK

  • Could not find com.voidhash:sdk or com.voidhash:ui. The includeBuild path in settings.gradle.kts doesn't point at the clone's libraries/android directory. Gradle substitutes those coordinates only from an included build.
  • SDK location not found in the included build. Set ANDROID_HOME, or copy local.properties into the clone's libraries/android directory.
  • Android Gradle Plugin version conflicts. The SDK's build uses AGP 8.9.0 and Kotlin 2.0.21; build your app with the same versions.

See Install the SDK.

Products are empty

getProducts() returns only products that are configured in your project and that Google Play returns for this device.

  • initialize() hasn't finished, or never loaded your configuration. On a cold offline launch the list is empty. Look for SCHEMA_FETCH_FAILED or AUTHENTICATION_FAILED diagnostics; the latter means the publishable key is wrong.
  • The product isn't mapped to a Google Play product, or the IDs differ. Check the mapping in Products and perks.
  • Google Play doesn't offer the product to this device. The product or base plan isn't active, the app's package name differs from the one in Play Console, the app was never uploaded to a testing track, or the device's Google account isn't a tester.
  • FAILED_TO_GET_PRODUCTS is thrown. Google Play couldn't be reached. Retry later.

In development mode, products come from your project, not Google Play; give each one a billing duration.

The paywall doesn't appear

Log result.error.code from FlowResult.Failed:

CodeFix
FLOW_RENDERER_MISSINGPass paywallRenderer = VoidhashUiPaywallRenderer() in VoidhashOptions.
FLOW_NOT_ASSIGNEDDeploy a build and assign it to the location you pass, and check the slug's spelling. If you just changed the assignment, wait up to an hour or clear the app's data: answers are cached. See Paywall locations.
FLOW_UNSUPPORTED_PACKAGEThe renderer's native library is missing or wasn't built for this device: rebuild it as in Add the paywall renderer and use an arm64-v8a or x86_64 device. Otherwise the build needs a newer SDK: update your clone.
FLOW_UNAVAILABLEThe device has never resolved this location and is offline, or the download failed. Retry online, or list the location in preloadPlacements.
FLOW_PRESENTATION_FAILEDThe renderer couldn't show the flow or failed on screen. Turn on debug and check logcat for the message.
FLOW_DISABLEDThe client is disabled or shut down.

A renderer that can't run the deployed build makes the location look unassigned, so FLOW_NOT_ASSIGNED can also mean the native library is missing. Paywalls are in early access; if Studio shows no Paywalls section, ask us to turn it on.

A purchase doesn't unlock the perk

  • The product doesn't grant the perk. Attach the perk to the product in Studio.
  • You check a different slug. hasActivePerk takes the perk's slug, not the product's.
  • Voidhash hasn't recorded the purchase yet. purchase returns after 10 seconds even if Voidhash hasn't answered. Read getCurrentPerson(forceFetch = true) again; TRANSACTION_SYNC_DEFERRED means the SDK is still sending it.
  • Voidhash refused the purchase. TRANSACTION_REJECTED means Google Play isn't connected for this package name. A debug build with an applicationIdSuffix has a different package name. Connect Google Play (Help center), then relaunch.
  • The environment doesn't match the key. A test key doesn't see production access, and a store sandbox purchase unlocks production only while your project allows it. See Environments.
  • The person changed. A purchase belongs to the identity that made it. See Identify users.

Test purchases with license testers

Google Play purchases need an app installed from Google Play.

  1. Upload a release build signed with your upload key to an internal or closed testing track.
  2. Add the tester's Google account under License testing in Play Console, and to the track.
  3. Install the app from the track's opt-in link on a device signed in with that account.
  4. Use the production publishable key. Purchases are store sandbox purchases and appear in Studio under Sandbox.

BILLING_CONNECTION_FAILED means Google Play services are missing or updating, or the account can't buy. Emulators need a Google Play system image. To test without Google Play, use development mode. See Test purchases (Help center).

Purchases are acknowledged twice in observer mode

When another billing integration owns purchases, Voidhash must not acknowledge or consume them.

  • readOnly isn't set. Without it, the SDK acknowledges and consumes purchases it finds at launch, so a consumable can be consumed before your integration credits it. Set readOnly = true before initialize(). See Observer mode.
  • Your app calls purchase or presents paywalls. In observer mode those fail with READ_ONLY_PURCHASE_NOT_ALLOWED; buy through your integration and call reportTransaction.
  • setReadOnly(false) ran during a migration. Ownership switches at once for new purchases. Switch only when you remove the other integration's purchase handling.

Events don't show up

  • Consent isn't granted. ANALYTICS_CONSENT_DENIED means analyticsConsent is DENIED or PENDING. See Analytics consent.
  • Events are still queued. The SDK sends every 5 seconds in the foreground. Call flush() and check pending. ANALYTICS_SEND_FAILED means delivery is being retried.
  • You're looking at the wrong environment. Events take the environment of the key that sent them; debug builds on the test key appear under Test.
  • The event is blocked or invalid. Check Settings → Events for a blocked name, and look for ANALYTICS_EVENT_INVALID or ANALYTICS_EVENT_DROPPED.
  • Voidhash runs in another process. SECONDARY_PROCESS_INERT means it was configured outside the main process. See Create the client.

See Check your data for what Voidhash received and rejected, and Rejected after capture for why.

Next steps

  • Errors for every code.
  • Troubleshooting across platforms.
  • Ask us on Discord.

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

PreviousDiagnostic codesNextWeb SDK

On this page

Gradle can't resolve the SDKProducts are emptyThe paywall doesn't appearA purchase doesn't unlock the perkTest purchases with license testersPurchases are acknowledged twice in observer modeEvents don't show upNext steps