Error codes
Every PurseException carries one PurseErrorCode. The names match the web SDK's error codes exactly, and exception.documentationLink points at the matching anchor of that page. This page lists what each code means on Android and the action expected from your app.
Exception families: PurseSessionException (decoding the session), PurseCheckoutException (the checkout's own rules), PartnerUiException (a partner's native step), PaymentApiException (HTTP and transport). Every exception is under the PurseException root.
Session
| Code | Exception | Meaning | Expected action |
|---|---|---|---|
SESSION_MALFORMED | PurseSessionException.SessionMalformed | The widgetData string is not a client session, or an unknown shape | A bug in the hand-over from your backend. Do not show a checkout; log and fix |
EXPIRED_SESSION | PurseCheckoutException.SessionExpired | A submit on an expired session, or setSession with an expired one. The watchdog throws nothing: it only sets sessionState to EXPIRED. A refused setSession leaves the current session and its state unchanged | Mint a new client session and call setSession |
SUBMIT_BLOCKED | PurseCheckoutException.SubmitBlocked | A submit is in flight, or the session already paid, was declined or terminated. state says which. Android only | Do nothing on SUBMITTING; otherwise get the outcome from your backend and move on |
CHECKOUT_TORN_DOWN | PurseCheckoutException.CheckoutTornDown | A call that reaches the network, hands out a host or replaces the session after teardown(). Android only | A lifecycle bug: the checkout outlived its screen. Build a new one |
Payment
| Code | Exception | Meaning | Expected action |
|---|---|---|---|
PAYMENT_NOT_FULFILLED_ON_SUBMIT | PurseCheckoutException.PaymentNotFulfilled | The split does not cover the amount, or no primary is set | Guard your Pay button with isPaymentFulfilled; highlight the missing amount |
ELEMENT_NOT_FULFILLED | PurseCheckoutException.ItemNotFulfilled | A form in the split is incomplete or invalid (the card form, a CVV field) | Same guard; focus the form, its fields show their own errors |
METHOD_DISABLED | PurseCheckoutException.MethodDisabled | setPrimary or setPrimaryToken on a disabled item, or an element created for a technically disabled one. disabled says why | Render the item as disabled from its disabled state; see Method states |
METHOD_NOT_IMPLEMENTED | PurseCheckoutException.NoPluginRegistered, NoSecondaryConfig | No plugin for the chosen method (usually a missing partner artifact), or no config for a gift card issuer | Add the artifact or disabledMethods; register a SecondaryConfig |
ON_BEFORE_VALIDATE_HOOK_FAILED | PurseCheckoutException.HookFailed (hook == "onBeforeValidate") | Your onBeforeValidate threw; nothing was sent, the split is intact | Your own failure is the cause; fix or show it, the shopper can submit again |
POST_VALIDATE_FAILED | PurseCheckoutException.HookFailed (hook == "onRedirection") | Your onRedirection threw; the redirect was not opened | /validate already answered, so the session is spent: get the outcome from your backend or start a new client session |
VALIDATE_FAILED | PurseCheckoutException.ValidateFailed | /validate failed, or a client-side check before it (no vault token collected). outcomeUnknown is true when the request left and no answer came back | If outcomeUnknown, get the outcome from your backend before showing anything; else show an error |
PARTNER_UI_ERROR | PartnerUiException | A partner's native step failed: its SDK returned an error, a tokenization was refused, the redirect Activity could not complete. The partner's exception is the cause. Android only | Show an error for this method and let the shopper pick another; the method may also be disabled |
UI_VALIDATION_FAILED_ERROR | Declared for parity with the web SDK, not raised on Android |
Gift cards (secondary methods)
| Code | Exception | Meaning | Expected action |
|---|---|---|---|
SECONDARY_METHOD_WRONG_PAN_FORMAT | PurseCheckoutException.InvalidSecondaryCard | The card number does not match the issuer's format | Validate with secondaryConfig(method).validatePan first; show a field error |
SECONDARY_METHOD_WRONG_CVV_FORMAT | InvalidSecondaryCard | The CVV does not match the issuer's format | Same with validateCvv |
SECONDARY_METHOD_REQUIRED_CVV | InvalidSecondaryCard | This card needs a CVV and none was given | Ask for it when requiresCvv(pan) is true |
FAILED_TO_INIT_SECONDARY_TOKEN | PurseCheckoutException.SecondaryTokenizationFailed | The issuer refused the card | Show "card not accepted"; let the shopper correct it |
SECONDARY_TOKEN_EMPTY_BALANCE | SecondaryTokenizationFailed | The card has no balance, or a saved card's balance is not resolved yet | Show the empty balance; for a saved card wait for balanceResolved |
INVALID_TAKE_AMOUNT | PurseCheckoutException.InvalidTake | applySecondary(token, amount) with a negative amount, above the balance or above what is left | Clamp the slice to min(balance, remainingAmountToPay) |
MAX_AMOUNT_REACHED | InvalidTake | The slice exceeds the issuer's maximum per payment | Clamp to the method's maxAmount |
USAGE_LIMIT_ERROR | InvalidTake | The issuer's per-session usage limit is spent by the cards already in the split | Tell the shopper no more cards of this issuer can be added |
Wallet and saved instruments
| Code | Exception | Meaning | Expected action |
|---|---|---|---|
MISSING_WALLET_SESSION | PurseCheckoutException.WalletOperationFailed | Saving, renaming, favoriting or deleting needs a wallet session the client session does not carry | Hide wallet features, or create the client session with a wallet session |
MISSING_TOKEN | WalletOperationFailed | The token is not in the wallet anymore | Refresh the list from paymentTokens |
INVALID_TOKEN_NAME | WalletOperationFailed | The label does not match ^[a-zA-Z0-9\s]{1,25}$: empty, longer than 25 characters, or with characters other than letters, digits and spaces | Show a field error |
TOKEN_NAME_EXISTS | WalletOperationFailed | Another token carries that label | Show a field error |
TOKEN_NOT_REGISTERABLE | WalletOperationFailed | registerSecondary on a gift card the issuer does not let you keep | Check canBeRegistered before offering to save |
METHOD_NOT_REGISTERABLE | WalletOperationFailed | register on a card method whose save_token_mode forbids saving | Check canBeRegistered before offering to save |
SET_WALLET_SESSION_FAILED, FAILED_TO_DELETE_ALL_TOKENS | Declared for parity with the web SDK; a failing wallet call surfaces as API_ERROR on Android |
Instalment simulation
| Code | Exception | Meaning | Expected action |
|---|---|---|---|
METHOD_IS_NOT_SIMULABLE | PurseCheckoutException.MethodNotSimulable | simulateLoan on a method without the simulable flag | Offer the simulation only when method.simulable |
INVALID_LOAN_SIMULATION | PurseCheckoutException.LoanSimulationFailed | The partner refused the amount or returned no schedule | Hide the schedule; the method stays payable |
Transport
| Code | Exception | Meaning | Expected action |
|---|---|---|---|
API_ERROR | PaymentApiException | A Payment API call failed: transport failure (status == null), non-2xx status, or an unusable response. errorCode is the API's own reason, path the request | isSessionTerminal: new session. isRetryable: offer a retry. Otherwise show an error |
UNKNOWN_ERROR | Declared for parity with the web SDK, not raised on Android |
Codes that exist only on the web
BRAND_NOT_BELONGS_TO_DETECTED, ELEMENT_RENDER_FAILED, PAYMENT_TOKEN_NOT_FOUND_IN_SESSION, INVALID_INIT_PARAMS, FAILED_TO_ADD_TOKEN, TOKEN_ALREADY_EXISTS describe situations that cannot happen with a native element and have no Android counterpart. SUBMIT_BLOCKED, CHECKOUT_TORN_DOWN and PARTNER_UI_ERROR exist only on Android.