Errors
Structured error codes and recovery guidance for the Swift SDK.
When an SDK call fails, it throws. Every error the SDK throws is a typed error that carries a
code string, and its string form is "CODE: message". The code tells you which operation
failed and what to do next. Match on code when the recovery differs by cause, and report the full
error for everything else.
This example handles one specific code and lets every other error propagate:
do {
let products = try await voidhash.getProducts()
} catch let error as VoidhashStoreError where error.code == "FAILED_TO_GET_PRODUCTS" {
// retry, fall back to cached products, …
}Operation codes
These codes name the client operation that failed. The message text is informational. Never match on it.
| Code | Thrown by | Recovery guidance |
|---|---|---|
AUTHENTICATION_FAILED | getCurrentPerson(), getFeatureFlags() | Check the publishable key. Thrown once, only when nothing is cached. |
CONFIGURATION_MISSING | Embedded calls on a disabled or replaced client | Call the client that replaced it. |
FAILED_TO_GET_PRODUCTS | getProducts() | Retry, or render the screen without store metadata. |
FAILED_TO_RESTORE_PURCHASES | restorePurchases() | The App Store could not be reached. Prompt the customer to retry. |
FAILED_TO_SHOW_MANAGE_SUBSCRIPTIONS | showManageSubscriptions() | Link to the App Store subscription settings instead. |
INVALID_ARGUMENT | identify() | Pass an ID Voidhash accepts. The current identity is unchanged. |
INVALID_ARGUMENT | setPersonAttributes() | Pass only strings, numbers, booleans, or nil. Nothing is saved. |
INVALID_TRANSACTION | reportTransaction(...) | Supply a non-empty original App Store transaction ID. |
RECONCILE_TRANSACTIONS_FAILED | restorePurchases() | Prompt the customer to retry. |
USER_CANCELLED | restorePurchases() | The customer dismissed the App Store sign-in. Do nothing. |
StoreKit errors never reach your app directly: the SDK wraps them in these codes and keeps
StoreKit's description in the message. Passing an unverified StoreKit result to
reportTransaction(...) throws its verification error.
identify() and setPersonAttributes() do not throw for network failures or a rejected
publishable key: the SDK saves the write and sends it later. They throw a VoidhashApiError only
when Voidhash rejects the write for good, and a rejected identify() restores the previous
identity. An anonymous ID that already belongs to a different account is not an error:
identify() signs the customer in without that ID's history and reports the
PERSON_WRITE_REJECTED diagnostic. When Voidhash rejects a write the SDK had saved for later, it
drops it and reports the same diagnostic.
Purchase codes
purchase(product:) throws when the purchase did not go through. Cancellation and pending approval
are expected outcomes, so match them separately from real failures.
| Code | Meaning |
|---|---|
USER_CANCELLED | The customer dismissed the App Store sheet. Do nothing. |
PURCHASE_PENDING | The purchase awaits approval, such as Ask to Buy. The SDK syncs it once it clears, and access arrives then. |
INVALID_PRODUCT_ID | The App Store did not return the product. Check the product mapping in Studio and the App Store Connect setup. |
OFFER_UNAVAILABLE | The promotional offer passed as offerId cannot be applied, for example because the customer is not eligible. Nothing was bought; offer the regular product instead. |
TRANSACTION_VERIFICATION_FAILED | StoreKit could not verify the transaction. Report the full error. |
PURCHASE_FAILED | StoreKit failed the purchase. The message carries StoreKit's description. Let the customer try again. |
READ_ONLY_PURCHASE_NOT_ALLOWED | The SDK runs in observer mode, which never starts a purchase. Buy through your other billing SDK, or see Observer mode. |
A purchase started from a paywall reports the same failures through onWarning and shows them
on the paywall. A cancelled purchase is not reported.