On this page Handle errors by categoryCancellation and recoveryRelease checksDiagnostic informationRoute errors from callbacks
APP SDK / Android · iOS

Errors and release checks

Handle cancellation, session changes and business conflicts, and check device permissions, payment callbacks and release configuration.

Handle errors by category

Error Host response
REQUEST_ABORTED End loading after cancellation; inspect recovery results as needed instead of showing a generic network failure
AUTH_CHANGED Consent or account/token state changed; discard stale UI results, inspect the session and recreate clients
AUTH_EXPIRED Platform session expired; sign in again or refresh through the platform flow
CLOUD_BUSY, SHOP_BUSY Conflicting operation exists; wait for settlement and refresh instead of repeatedly submitting mutations
NAVIGATION_ACTIVE End navigation before switching or removing the vehicle
NETWORK_ERROR, REQUEST_TIMEOUT Outcome may be unknown; query and recover before deciding to retry
RELEASE_PENDING Complete pending nearby revocation before starting another binding
2901 Binding challenge or version conflict; query authorization again rather than blindly resubmitting the old challenge
LEGACY_SCOPE_REQUIRED, LEGACY_SCOPE_CONFLICT Legacy origin is unclaimed or belongs elsewhere; verify it using upgrade guidance, never claim automatically

HTTP uses HTTPS with a base including /api/v1; the SDK appends /app/... and does not follow redirects. Retain server error codes and HTTP status for diagnosis. Do not treat every failure as unavailable Bluetooth.

Cancellation and recovery

After cancellation, wait for the final callback before starting another mutually exclusive task. Cancellation is not a transaction rollback: binding, unbinding or payment may already have been confirmed remotely. Recover using authoritative server and terminal state.

Never automatically replay vehicle commands, restart payment or use a new purchase UUID to retry an unknown result. Centralize device workflow coordination so screens share the current account, target vehicle and operation lifecycle.

Release checks

Area Verify
Registration Correct clientId, manufacturer scope, API environment and enabled services
Privacy and permissions Related capabilities remain inactive before consent; denial, withdrawal and reauthorization work
Vehicles Initial/repeated pairing, incorrect PIN, cancellation, switching, unbinding and account changes
Connectivity Authentication still matches the target after Bluetooth or hotspot denial, disconnect and reconnect
Commerce Manufacturer mismatch is rejected; address/price changes require a new quote; duplicate taps do not duplicate orders
Payment Cold-launch and foreground URLs, cancellation and timeout recovery, server order queries; unconfirmed results never appear settled
Lifecycle Background/foreground, process restart, token refresh and navigation restrictions
Binaries and signing Correct platform package and version, host signing, system capabilities and third-party notices

Verify these paths on real phones with supported terminals. Simulator runs, compilation, installation and successful cloud responses prove different stages; they do not replace actual vehicle-control and payment acceptance.

Diagnostic information

Report SDK and OS versions, action name, error code, time and reproducible steps. Include whether the account, vehicle or network changed. Redact logs and avoid collecting tokens, PINs, Wi-Fi passwords, device credentials, complete personal addresses or signed payment parameters.

Contact the platform for package delivery and registration issues. For instrument firmware and FreeRTOS, use the hardware SDK docs.

Route errors from callbacks

This example maps error codes to host UI decisions without replaying requests. Pass the callback to a cloud operation such as list. onValue receives the current operation’s result; onFailure ends loading and chooses a prompt, sign-in or query/recovery flow. The host still checks the operation generation.

import net.oou.mobile.ResultCallback

enum class FailureAction {
    CANCELLED, RECREATE_SESSION, SIGN_IN, WAIT_FOR_ACTIVE,
    QUERY_AND_RECOVER, INSPECT_BUSINESS_ERROR
}

fun cloudCallback(
    onValue: (Any?) -> Unit,
    onFailure: (FailureAction, String) -> Unit
): ResultCallback = object : ResultCallback {
    override fun resolve(value: Any?) = onValue(value)
    override fun reject(code: String, message: String?, cause: Throwable?) {
        val action = when (code) {
            "REQUEST_ABORTED" -> FailureAction.CANCELLED
            "AUTH_CHANGED" -> FailureAction.RECREATE_SESSION
            "AUTH_EXPIRED" -> FailureAction.SIGN_IN
            "CLOUD_BUSY", "SHOP_BUSY" -> FailureAction.WAIT_FOR_ACTIVE
            "NETWORK_ERROR", "REQUEST_TIMEOUT" -> FailureAction.QUERY_AND_RECOVER
            else -> FailureAction.INSPECT_BUSINESS_ERROR
        }
        onFailure(action, code)
    }
}