microg/GmsCore · critical · RuntimeException
Failed to obtain login token.
Error message
Failed to obtain login token.
What it means
createIAPCore builds an IAPCore using auth data from AuthManager.getAuthData; when it returns null (no login token for the account) this RuntimeException is thrown. It means the device has no usable Google auth token for the given account, so IAP API calls cannot be authenticated.
Source
Thrown at vending-app/src/main/java/org/microg/vending/billing/InAppBillingServiceImpl.kt:169
createIAPCore(
context,
buyFlowCacheEntry.account,
buyFlowCacheEntry.packageName
).requestAuthProofToken(password)
}
return runBlocking { deferred.await() }
}
private fun createIAPCore(context: Context, account: Account, pkgName: String): IAPCore {
val key = "$pkgName:${account.name}"
val cacheEntry = iapCoreCacheMap[key]
if (cacheEntry != null) {
if (cacheEntry.expiredAt > System.currentTimeMillis())
return cacheEntry.iapCore
iapCoreCacheMap.remove(key)
}
val authData = AuthManager.getAuthData(context, account)
?: 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.")View on GitHub (pinned to 157c9d86ac)
Solutions
- Ensure the device has a signed-in Google account and the app targets the correct account name.
- Trigger account re-authentication (re-add account or refresh credentials) so AuthManager can obtain a token.
- Check network connectivity and microG auth component health; retry after token refresh succeeds.
- Catch this RuntimeException in the billing path and surface a 'sign-in required' state to the user.
Example fix
// before
val history = billing.getPurchaseHistory(api, pkg, type, extras)
// after
try {
val history = billing.getPurchaseHistory(api, pkg, type, extras)
} catch (e: RuntimeException) {
if (e.message == "Failed to obtain login token.") promptSignIn()
else throw e
} Defensive patterns
Strategy: try-catch
Validate before calling
val accounts = AccountManager.get(context).getAccountsByType("com.google")
if (accounts.isEmpty()) promptSignIn() else proceedBilling() Type guard
fun hasGoogleAuth(account: Account?, context: Context): Boolean =
account != null && AuthManager.getAuthData(context, account) != null Try / catch
try {
billing.getPurchaseHistory(...)
} catch (e: RuntimeException) {
if (e.message?.contains("login token") == true) promptReAuth()
else throw e
} Prevention
- Verify a signed-in Google account exists before billing calls
- Handle token refresh failures with re-authentication
- Monitor network state; retry auth after connectivity returns
- Surface sign-in-required states instead of crashing
When it happens
Trigger: Any billing call (acquireRequest, getPurchaseHistory, consumePurchaseExtraParams, getSkuDetailsExtraParams, acknowledgePurchase, requestAuthProofToken) that goes through createIAPCore while AuthManager.getAuthData(context, account) returns null — no cached/refreshable auth token.
Common situations: Device not signed in or account removed; auth token refresh failing due to network/auth server issues; microG not permitted to fetch auth tokens; account credentials invalidated (password change, security events).
Related errors
- Required caller information missing
- Failed to retrieve device information.
- Failed to retrieve client information.
- No Google account found.
- Access denied, missing google package permission for
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/7c13e0c710acc6ff.
Report an issue: GitHub.