Troubleshooting
Find the cause of common integration problems by symptom, across every platform.
Find your symptom below for its most common causes, in order of likelihood. If you have an error code, look it up in Error codes; for general questions, see the FAQ. For platform-specific problems, see the troubleshooting pages for Swift, Kotlin, React Native and Web. For data problems, start at Analytics → Data health; see Check your data.
Before you dig in, confirm that Studio shows the same project and environment your build uses. A
vh_pk_test_... key records into Test, and TestFlight and Play test track purchases appear
under Sandbox. See Teams, projects and environments.
Products are empty
- The product isn't mapped to this store. The SDK returns only products that are mapped to the store it runs on and that the store returns. Check the mapping on the product in Products.
- The store doesn't return the product. App Store: the Paid Applications agreement must be active, and the bundle ID must match. Google Play: install the build from a Play test track as a license tester, not a sideloaded build.
- The publishable key was rejected. The SDK then returns an empty list without an error. Check the SDK's diagnostics and the key in API keys.
A paywall doesn't appear
presentFlow returns a failed result that says why:
- Not assigned. No deployed paywall is assigned to the location, or it uses a component this SDK version can't run. See Paywall locations and Build and deploy.
- Renderer missing. The app was built without the paywall renderer. Each SDK's paywalls page shows how to add it.
- Unavailable. The device has never loaded this location and can't reach Voidhash.
If your team doesn't see Paywalls in Studio, the feature isn't turned on for it yet; ask on Discord.
A purchase doesn't unlock access
- No perk is attached. The product must grant the perk your app checks. See Products and perks.
- The store product isn't mapped. Voidhash keeps the purchase but grants nothing until you map the store product. Map it within a year and the purchase is applied with its perks. See Products and perks.
- Observer mode without reporting. In observer mode, call
reportTransactionafter each purchase your billing SDK makes. - It went to another person. Call
identifybefore the purchase, or check the person the purchase is on in People. See People and identity.
Restore finds nothing
- Another store account. Restore returns purchases of the Apple ID or Google account signed in on the device.
- Another environment. Sandbox purchases restore only into sandbox builds.
- Paid access sharing is
disabled. A purchase made by another user of your app stays with them. The default,transfer, moves it to the person who restores. Check the setting withGET /api/v1/projects/{projectId}/settings, the MCP toolget_project_settingsorvoidhash settings view; see Project settings.
Webhooks don't arrive
- Environment mismatch. A test endpoint receives only non-production events; a production endpoint receives only production events, plus store sandbox events while sandbox purchases unlock production.
- Not subscribed. The endpoint must list the event types you expect.
- The endpoint is failing. Only a
2xxwithin 30 seconds counts; redirects aren't followed. After 20 consecutive failures the endpoint is set to Failed. Check its delivery log.
See Webhook delivery.
Webhook signatures don't verify
- The body changed. Verify the raw request body. Parsing and re-serializing JSON changes it.
- Wrong secret. Each endpoint has its own secret, and rotating it invalidates the old one at once, including for pending retries.
- Clock skew. The library helpers reject timestamps more than 300 seconds from your server's clock.
See Signatures.
Events are missing
- Analytics consent. While consent is
deniedorpending, the SDK drops analytics events. - The event is turned off or blocked in Settings → Events.
- The event was rejected. Analytics → Data health lists rejected events and why.
Recent events appear in Activity → Analytics events. See Events.
Sandbox purchases unlock production
Store sandbox purchases, including TestFlight and App Review, unlock access in production apps by
default, so reviewers can test your purchases. To stop this, set storeSandbox.isUnlockingProduction
to false with PATCH /api/v1/projects/{projectId}/settings, the MCP tool
update_project_settings, or voidhash settings set store-sandbox-unlocks-production off; see
Project settings. Test purchases, such as
Stripe test mode, never unlock production.
Stripe purchases aren't attributed
- No distinct ID. Set
voidhash_distinct_idin the Checkout Session and subscription metadata, or on the Stripe customer. - Payment Links, the pricing table or the Buy Button. They can't carry per-buyer metadata, so purchases land on a stand-in person until your backend sets the customer's metadata.
See Where Voidhash reads the ID.
The CLI can't authenticate
- Not signed in to this server. Run
voidhash login.voidhash whoamishows the server; a profile orVOIDHASH_API_URLthat points elsewhere needs its own sign-in. - An environment key takes over.
VOIDHASH_API_KEYis used instead of your stored sign-in. Unset it, or check that it is valid for this project. - The code expired or was denied. Run
voidhash loginagain.
See CLI.
An MCP agent can't connect
- Not signed in. Start the agent's sign-in again: in Claude Code run
/mcp, in Codex runcodex mcp login voidhash. - Unsupported client. The server speaks stateless streamable HTTP; clients that support only session-based MCP versions can't connect.
- A tool is missing. Your role doesn't allow it in that project, or the agent is read-only. Agents unused for 90 days are signed out.
See MCP server.
Get help
Ask on Discord or open an issue on GitHub. Include:
- your project slug and the platform;
- the SDK or library version;
- the
Request-Idresponse header of a failing API request, if there is one; - timestamps of what happened, with time zone;
- the person's distinct ID or the store transaction ID, if relevant.
Never share secret keys, webhook secrets, store credentials or personal data of your users.
Next steps
Something wrong or missing on this page? Tell us by email or on Discord.