Skip to documentation
Open dashboard
Docs/Operate and troubleshoot

Troubleshooting

Diagnose missing purchases, inactive access, store failures, and reporting differences.

Download this chapter
On this page

Start with the exact failing boundary: account/session, app identity, store credential, receipt verification, access mapping, presentation, delivery, or reporting. Repeating every setup step at once makes the cause harder to isolate.

Account, invitation, and permission failures

SymptomCheckNext action
Sign-in failsCorrect account and deployment; password rules do not change an existing passwordUse the intended account or password reset
Verification/reset link failsLatest link, expiry, correct browser/accountRequest a new link and continue locally
Invitation email mismatchThe signed-in email versus the invited emailUse the invited account
View access / 403Project role and email verificationAsk an owner/admin for the needed role
Shared analysis cannot openRecipient's project/app membershipGrant legitimate membership; a URL alone grants none
Resource not found after switchingCurrent project/app versus the old linkReselect scope and reopen the resource

Default link lifetimes are 24 hours for verification, 30 minutes for reset, and seven days for invitations. Missing email can also indicate gateway configuration or delivery failure. Accounts.

A store credential will not save

For Apple, use the In-App Purchase .p8, its correct Key ID, and Issuer ID. The filename can populate Key ID but cannot prove the key is the right kind or belongs to the intended team. In CLI setup, check the selected provider and the existence of the bundle record.

For Google, choose the service-account key JSON, not a Desktop OAuth client JSON. Check its token URI and account email, the package-level Play grants, and API enablement. Organization policies can legitimately prevent key creation.

Managed credential storage requires the installation's encryption-key configuration. A 409 can indicate unavailable managed storage rather than a bad store password. The credential validator's file limits and the hosted API envelope limit are different; see Limits for large uploads.

Apple purchase fails before reaching CherrySub

If StoreKit itself returns an error (including an unexplained 3504), first determine whether it happened before any signed transaction was produced or any receipt request reached the API. Inspect tester/build eligibility, agreements, product availability, bundle/app IDs, network, and storefront logs. A pre-purchase store error is not repaired by fabricating a JWS or disabling backend verification.

For reproducible store-side failures, collect non-secret timestamps, product/bundle IDs, build information, and the store error domain/code for the appropriate Apple support path. Do not assume every 3504 error has the same cause.

Purchase exists but access is inactive

  1. Confirm the selected app and the broker's App User ID.
  2. Find the verified transaction and its current owner.
  3. Check the exact product/platform access mapping and its grant mode.
  4. Compare expiry and refund/revocation evidence.
  5. Inspect other grant contributions to the same access level.
  6. Refresh the subscriber response and clear stale application-owned access UI.

A product set controls presentation, not access. A mapping edit does not retroactively rewrite all past evidence. Restore can change one purchase's ownership without merging identities. Access · Ownership.

Receipt/API errors

StatusCommon meaningHandling
400 / 422Bad request shape or store evidence/identity validationCorrect the payload or configuration; do not blindly retry unchanged invalid data
401Missing, expired, revoked, cross-app, or invalid credential/tokenRefresh once where supported; verify broker subject and deployment
403Wrong key kind or insufficient hosted project permissionUse the documented trust boundary
404Missing scoped resource or a not-yet-created customer aliasConfirm scope; do not treat a missing subscriber as active
409Configuration or lifecycle conflictInspect current state before retrying
413Request too largeUse the supported payload, not an entire unrelated receipt bundle
429ThrottledRespect Retry-After and reduce concurrent retries
503Verifier/dependency/configuration unavailableInvestigate readiness and retry transient failures with bounds

Runtime API errors use an error field. Hosted account/dashboard errors use message and sometimes a machine-readable code. The API references and hosted API distinguish them.

Notifications or webhooks are missing

Apple notifications require the V2 URL and matching signed app identity. Google RTDN requires an authenticated Pub/Sub push audience/email and a successful authoritative purchase read for purchase notifications. A test notification alone does not prove paid purchase access.

For outbound webhooks, confirm the endpoint is enabled, its filter matches a supported derived event, and the receiver returns 2xx. Inspect the head-of-line failed delivery. Verify signatures against raw bytes and the current/overlap secrets. Fix the receiver before replay; replay preserves its message ID.

Charts disagree with another report

Check app, environment, currency, UTC range, resolution, current-snapshot versus period series, and cohort anchor/window/maturity. Standard refund cohorts use purchase dates; realized LTV uses in-lifetime refund timestamps. Customer activity is not application engagement DAU. Net is not store proceeds after taxes/commission.

Missing history or accounting enrichment can leave incomplete financial data. Run rate uses observed effective duration, and partial-month movement buckets have preview limitations. See Metrics before escalating a supposed mismatch.

CLI failure after creating a key

The CLI prints the newly created key's ID when upload fails. Check cherrysub stores status APP_UUID first: a network timeout can happen after save. Revoke only an unused new key in the store console; old keys were retained. Apple private keys may not be downloadable again.

For a busy CLI profile, wait for the current command. Remove the reported lock file only after verifying no command is running. Use separate signed-in profiles for concurrent jobs. CLI recovery.