microg/GmsCore · error · RuntimeException
No Google account found.
Error message
No Google account found.
What it means
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.
Source
Thrown at vending-app/src/main/java/org/microg/vending/billing/InAppBillingServiceImpl.kt:187
?: throw RuntimeException("Failed to obtain login token.")
val deviceEnvInfo = createDeviceEnvInfo(context)
?: throw RuntimeException("Failed to retrieve device information.")
val clientInfo = createClient(context, pkgName)
?: throw RuntimeException("Failed to retrieve client information.")
val iapCore = IAPCore(context.applicationContext, deviceEnvInfo, clientInfo, authData)
iapCoreCacheMap[key] =
IAPCoreCacheEntry(iapCore, System.currentTimeMillis() + EXPIRE_MS)
return iapCore
}
}
private fun getPreferredAccount(extraParams: Bundle?): Account {
val name = extraParams?.getString("accountName")
name?.let {
extraParams.remove("accountName")
}
return getGoogleAccount(context, name)
?: throw RuntimeException("No Google account found.")
}
private fun isBillingSupported(
apiVersion: Int,
type: String?,
packageName: String,
extraParams: Bundle?
): Bundle {
if (!VendingPreferences.isBillingEnabled(context)) {
Log.w(TAG, "isBillingSupported: Billing is disabled")
return resultBundle(BillingResponseCode.BILLING_UNAVAILABLE, "Billing is disabled")
}
if (apiVersion !in 3..28) {
return resultBundle(BillingResponseCode.BILLING_UNAVAILABLE, "Client does not support the requesting billing API.")
}
if (extraParams != null && apiVersion < 7) {
return resultBundle(BillingResponseCode.DEVELOPER_ERROR, "ExtraParams was introduced in API version 7.")
}View on GitHub (pinned to 157c9d86ac)
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.
Example fix
// before
val extras = Bundle().apply { putString("accountName", "user@gmail.com") }
billing.getBuyIntent(api, pkg, sku, type, developerPayload, extras)
// after
val accounts = AccountManager.get(context).getAccountsByType("com.google")
if (accounts.none { it.name == "user@gmail.com" }) {
promptAddAccount() // or drop the accountName extra to use the default
}
val extras = Bundle().apply { if (accountExists) putString("accountName", "user@gmail.com") }
billing.getBuyIntent(api, pkg, sku, type, developerPayload, extras) Defensive patterns
Strategy: validation
Validate before calling
val accounts = AccountManager.get(context).getAccountsByType("com.google")
if (accounts.isEmpty()) promptAddAccount()
val requested = extraAccountName
if (requested != null && accounts.none { it.name == requested }) dropAccountExtraOrPrompt() Type guard
fun hasGoogleAccount(context: Context, name: String? = null): Boolean {
val accounts = AccountManager.get(context).getAccountsByType("com.google")
return if (name == null) accounts.isNotEmpty() else accounts.any { it.name == name }
} Try / catch
try {
billing.getPurchases(...)
} catch (e: RuntimeException) {
if (e.message == "No Google account found.") promptSignIn()
else throw e
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Fresh device/emulator without a Google account; microG account not configured; app passes a wrong/stale accountName extra; user signed out between purchase steps.
Related errors
- Failed to obtain login token.
- Required caller information missing
- oauthToken is null
- account is null
- Nothing cached: $cacheKey
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/9f4764cfa51dc3fe.
Report an issue: GitHub.