{"record":{"id":"9f4764cfa51dc3fe","repo":"microg/GmsCore","slug":"no-google-account-found","errorCode":null,"errorMessage":"No Google account found.","messagePattern":"No Google account found\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"vending-app/src/main/java/org/microg/vending/billing/InAppBillingServiceImpl.kt","lineNumber":187,"sourceCode":"                ?: throw RuntimeException(\"Failed to obtain login token.\")\n            val deviceEnvInfo = createDeviceEnvInfo(context)\n                ?: throw RuntimeException(\"Failed to retrieve device information.\")\n            val clientInfo = createClient(context, pkgName)\n                ?: throw RuntimeException(\"Failed to retrieve client information.\")\n            val iapCore = IAPCore(context.applicationContext, deviceEnvInfo, clientInfo, authData)\n            iapCoreCacheMap[key] =\n                IAPCoreCacheEntry(iapCore, System.currentTimeMillis() + EXPIRE_MS)\n            return iapCore\n        }\n    }\n\n    private fun getPreferredAccount(extraParams: Bundle?): Account {\n        val name = extraParams?.getString(\"accountName\")\n        name?.let {\n            extraParams.remove(\"accountName\")\n        }\n        return getGoogleAccount(context, name)\n            ?: throw RuntimeException(\"No Google account found.\")\n    }\n\n    private fun isBillingSupported(\n        apiVersion: Int,\n        type: String?,\n        packageName: String,\n        extraParams: Bundle?\n    ): Bundle {\n        if (!VendingPreferences.isBillingEnabled(context)) {\n            Log.w(TAG, \"isBillingSupported: Billing is disabled\")\n            return resultBundle(BillingResponseCode.BILLING_UNAVAILABLE, \"Billing is disabled\")\n        }\n        if (apiVersion !in 3..28) {\n            return resultBundle(BillingResponseCode.BILLING_UNAVAILABLE, \"Client does not support the requesting billing API.\")\n        }\n        if (extraParams != null && apiVersion < 7) {\n            return resultBundle(BillingResponseCode.DEVELOPER_ERROR, \"ExtraParams was introduced in API version 7.\")\n        }","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/vending-app/src/main/java/org/microg/vending/billing/InAppBillingServiceImpl.kt#L169-L205","documentation":"getPreferredAccount resolves the account to use for billing operations: it takes the optional accountName extra, otherwise the default Google account; if getGoogleAccount finds none it throws this RuntimeException. It means no Google account is available (or the requested one isn't present) to perform the billing call.","triggerScenarios":"Calling getBuyIntentExtraParams, getPurchaseHistory, getPurchasesExtraParams, consumePurchaseExtraParams, getSkuDetailsExtraParams, or acknowledgePurchase when the device has no signed-in Google account, or the accountName extra doesn't match any registered account.","commonSituations":"Fresh device/emulator without a Google account; microG account not configured; app passes a wrong/stale accountName extra; user signed out between purchase steps.","solutions":["Add a Google account on the device (or in microG account settings) before invoking billing APIs.","Check that the accountName extra matches an existing account (AccountManager.getAccounts) before calling.","Omit the accountName extra to use the device default account.","Catch RuntimeException and prompt the user to sign in, retrying the billing call afterwards."],"exampleFix":"// before\nval extras = Bundle().apply { putString(\"accountName\", \"user@gmail.com\") }\nbilling.getBuyIntent(api, pkg, sku, type, developerPayload, extras)\n// after\nval accounts = AccountManager.get(context).getAccountsByType(\"com.google\")\nif (accounts.none { it.name == \"user@gmail.com\" }) {\n    promptAddAccount() // or drop the accountName extra to use the default\n}\nval extras = Bundle().apply { if (accountExists) putString(\"accountName\", \"user@gmail.com\") }\nbilling.getBuyIntent(api, pkg, sku, type, developerPayload, extras)","handlingStrategy":"validation","validationCode":"val accounts = AccountManager.get(context).getAccountsByType(\"com.google\")\nif (accounts.isEmpty()) promptAddAccount()\nval requested = extraAccountName\nif (requested != null && accounts.none { it.name == requested }) dropAccountExtraOrPrompt()","typeGuard":"fun hasGoogleAccount(context: Context, name: String? = null): Boolean {\n    val accounts = AccountManager.get(context).getAccountsByType(\"com.google\")\n    return if (name == null) accounts.isNotEmpty() else accounts.any { it.name == name }\n}","tryCatchPattern":"try {\n    billing.getPurchases(...)\n} catch (e: RuntimeException) {\n    if (e.message == \"No Google account found.\") promptSignIn()\n    else throw e\n}","preventionTips":["Check for a Google account before any billing API call","Validate accountName extras against AccountManager entries","Prefer omitting accountName to use the device default","Handle sign-out mid-flow: re-check account between purchase steps"],"tags":["android","account","authentication","in-app-billing"],"backgroundTag":"authentication-required","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}