Errors, Logging and Troubleshooting
WirexError codes and reasons, logging, timeouts and the common failures of the Android SDK.
Before You Start
Read the following guides before proceeding:
| Guide | Why |
|---|---|
| Android SDK | Surfaces, isolation model and flows |
| SDK Setup | create(...), the credential provider and screen protection |
Where Errors Arrive
| Surface | Delivery |
|---|---|
| Reveal | snapshot.state Failed(error). load() throws only WirexDeclined |
| Collect | tokenizeTopUp / tokenizeOctDestination throw WirexError |
| 3-D Secure | outcome.error, code ORIGIN_REFUSED, DECLINED or UNAVAILABLE |
| Google Pay | ExecuteFailed and Failed events |
WirexError
WirexErrorcode | Handling |
|---|---|
UNAUTHORIZED | Refresh the access token. The SDK never retries a 401 |
ACTION_REQUIRED | Obtain a fresh action token and retry |
UPDATE_REQUIRED | Ship a newer SDK build |
INVALID_INPUT | Fix the input — see reason |
TEMPORARY | Retry when retryable is true. A timed-out request fails TEMPORARY and is retryable |
FAILED | Terminal |
reason | Meaning |
|---|---|
ACTION_TOKEN_REJECTED | The API rejected the action token. Mint a fresh GetCardDetails token |
CARD_ALREADY_LINKED | Collect: the card is already linked. Ask for a different card |
CARD_LIMIT_REACHED | Collect: the user holds the maximum number of saved cards. Remove one first |
INVALID_CARD_ID | Reveal: the card id is malformed |
fun describe(error: WirexError): String = when (error.code) {
WirexError.Code.UNAUTHORIZED -> "refresh the access token"
WirexError.Code.ACTION_REQUIRED -> "obtain a fresh action token and retry"
WirexError.Code.UPDATE_REQUIRED -> "ship a newer SDK build"
WirexError.Code.INVALID_INPUT -> when (error.reason) {
WirexError.Reason.CARD_ALREADY_LINKED -> "enter a different card"
WirexError.Reason.CARD_LIMIT_REACHED -> "remove a card first"
else -> "fix the highlighted field"
}
WirexError.Code.TEMPORARY -> if (error.retryable) "retry" else "give up"
WirexError.Code.FAILED -> "terminal"
}Other Types
WirexDeclinedis not an error state: the user said no and nothing was sent.WirexEnvironmentUnavailableis thrown byWirexEnvironment.resolve(name, chainId)and
WirexWalletEnvironment.resolve(name):UnknownName,NotBuilt,MalformedEndpoints,MissingChainId.
Thecreate(...)factories returnnullfor the same conditions. Show the reason; never fall back to another
environment.
Logging
Logging is off by default. Every logged value passes a redactor; tokens and card data are never handed to a
sink. Sinks are called on arbitrary threads and must not block.
| Surface | Option | Logcat tag |
|---|---|---|
| Reveal, Collect, 3-D Secure | logging = WirexLogging(level, sink). Presets: WirexLogging.DISABLED (default), WirexLogging.DEBUG, logcatLogging(level) | WirexappCardSdk |
| Google Pay | WirexWalletLogging with its own sink type and com.wirexapp.wallet.topup.logcatLogging(level). Default WirexWalletLogging.DISABLED | WirexWallet |
val reveal = WirexReveal.create(
credentials = credentials, chainId = "<chain id>",
logging = logcatLogging(WirexLogLevel.INFO),
timeouts = WirexTimeouts(connectMillis = 10_000, readMillis = 20_000),
)Log at DEBUG in development builds and WARN in release.
Timeouts
timeouts = WirexTimeouts(connectMillis, readMillis) on create(...). Both default to 15 seconds. A timed-out
request fails with code TEMPORARY and retryable = true.
Troubleshooting
| Symptom | Cause | Resolution |
|---|---|---|
| A revealed field is blank or will not unmask | FLAG_SECURE not active on the window; onRevealRefused fires | Pass the window with secureWindow(window) |
create(...) returns null | The build has no endpoints for that environment, or chainId is blank | Call WirexEnvironment.resolve(name, chainId) to get the reason |
Reveal or Collect fails with UNAUTHORIZED | Stale bearer. The SDK never retries a 401 | Check expiry and refresh inside accessToken() |
API answers 400 on every call | Both userEmail and userWallet are set | Return exactly one identity |
| Collect cannot tokenize | Billing details missing, or the user is not enrolled at the acquirer | Send every required billing field — see Collect a Card |
| The Pay button is unavailable | Checker not started, empty provider block, or the device is below the Google Pay floors | Start WirexWalletAvailabilityChecker with the real block; test on a device with Google Pay set up |
3-D Secure ends in PENDING | The payment is not settled yet | Not an error. Settle from the top-up status |
Updated about 3 hours ago
Did this page help you?

