microg/GmsCore · error · RuntimeException

Network request failed. message=${e.message}

Error message

Network request failed. message=${e.message}

What it means

IAPCore.getSkuDetails wraps every exception from the SKU-details network round trip (HTTP call, response decode, result parsing) in a RuntimeException with the message 'Network request failed. message=...'. The original exception type is lost; only its message is preserved.

Source

Thrown at vending-app/src/main/java/org/microg/vending/billing/core/IAPCore.kt:140

            val cacheEntry = skuDetailsCache.get(requestBody)
            if (cacheEntry != null) {
                val getSkuDetailsResult = GetSkuDetailsResult.parseFrom(GoogleApiResponse.ADAPTER.decode(cacheEntry).payload?.skuDetailsResponse)
                if (getSkuDetailsResult.skuDetailsList != null && getSkuDetailsResult.skuDetailsList.isNotEmpty()) {
                    Log.d("IAPCore", "getSkuDetails from cache ")
                    return getSkuDetailsResult
                }
            }
            Log.d("IAPCore", "getSkuDetails: ")
            val response = HttpClient().post(
                GooglePlayApi.URL_SKU_DETAILS,
                headers = HeaderProvider.getDefaultHeaders(authData, deviceInfo),
                payload = skuDetailsRequest,
                adapter = GoogleApiResponse.ADAPTER
            )
            skuDetailsCache.put(requestBody, response.encode())
            GetSkuDetailsResult.parseFrom(response.payload?.skuDetailsResponse)
        } catch (e: Exception) {
            throw RuntimeException("Network request failed. message=${e.message}")
        }
    }

    private fun createAcquireRequest(params: AcquireParams): AcquireRequest {
        val theme = 2

        val skuPackageName = params.buyFlowParams.skuParams["skuPackageName"] ?: clientInfo.pkgName
        val extendedPackageInfo = ExtendedPackageInfo(context, skuPackageName as String)
        val docId = if (params.buyFlowParams.skuSerializedDockIdList?.isNotEmpty() == true) {
            val sDocIdBytes = Base64.decode(params.buyFlowParams.skuSerializedDockIdList[0], Base64.URL_SAFE + Base64.NO_WRAP)
            DocId.ADAPTER.decode(sDocIdBytes)
        } else {
            val docIdBuilder = DocId.Builder()
            docIdBuilder.apply {
                backendDocId =
                    "${params.buyFlowParams.skuType}:$skuPackageName:${params.buyFlowParams.sku}"
                type = getSkuType(params.buyFlowParams.skuType)
                backend = 3

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Check device connectivity and that Google Play/microG account is signed in before calling
  2. Read e.message to identify the underlying cause (status code, null payload, etc.) since the original exception is wrapped
  3. Catch RuntimeException around getSkuDetails and surface a retryable billing error
  4. Retry with exponential backoff for transient network failures

Example fix

// before
val details = iapCore.getSkuDetails(params)
// after
val details = try {
    iapCore.getSkuDetails(params)
} catch (e: RuntimeException) {
    Log.w("Billing", "getSkuDetails failed: ${e.message}")
    null
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!isOnline(context)) return
require(accountSignedIn) { "Google account required for getSkuDetails" }

Try / catch

try {
    iapCore.getSkuDetails(params)
} catch (e: RuntimeException) {
    Log.w("Billing", "getSkuDetails failed: ${e.message}")
    retryWithBackoff()
}

Prevention

When it happens

Trigger: Calling getSkuDetails when the HTTP request throws (no network, timeout, non-200 status from HttpClient.get), the protobuf decode fails, or GetSkuDetailsResult.parseFrom throws (null/invalid payload).

Common situations: Device offline or Play Services unreachable; microG not signed in to a Google account; server returning unexpected payload causing parseFrom to throw; HTTP 4xx/5xx from the billing endpoint.

Related errors


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/dc80de916ca64c81. Report an issue: GitHub.