{"record":{"id":"17a9d56471c5b958","repo":"microg/GmsCore","slug":"account-is-null","errorCode":null,"errorMessage":"account is null","messagePattern":"account is null","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"play-services-core/src/main/kotlin/com/google/android/gms/semanticlocationhistory/extensions.kt","lineNumber":47,"sourceCode":"const val ODLH_SECURITY_DOMAIN = \"users/me/securitydomains/on_device_location_history\"\nconst val ODLH_SECURITY_DOMAIN_SHORT = \"on_device_location_history\"\n\nconst val E2EE_TYPE_URL = \"type.googleapis.com/geller.oneplatform.GellerE2eeElement\"\nconst val AES_GCM_IV_SIZE = 12\nconst val AES_GCM_TAG_BITS = 128\nconst val AES_KEY_SIZE = 32\n\nconst val SEMANTIC_TYPE_HOME = 1\nconst val SEMANTIC_TYPE_WORK = 2\nconst val SEARCH_WINDOW_DAYS = 30L\nconst val SECONDS_PER_DAY = 86400L\n\nsuspend fun Context.requestGellerOauthToken(accountName: String, scope: String = \"oauth2:https://www.googleapis.com/auth/webhistory\"): String {\n    val accountManager = AccountManager.get(this)\n    val account = accountManager.getAccountsByType(AuthConstants.DEFAULT_ACCOUNT_TYPE).find {\n        it.name == accountName\n    }\n    if (account == null) throw RuntimeException(\"account is null\")\n    return withContext(Dispatchers.IO) {\n        accountManager.blockingGetAuthToken(account, scope, true)\n    } ?: throw RuntimeException(\"oauthToken is null\")\n}\n\nsuspend fun Context.getObfuscatedGaiaId(accountName: String) = requestGellerOauthToken(accountName, AuthConstants.SCOPE_GET_ACCOUNT_ID)\n\nprivate val weakCachedKeyMap = WeakHashMap<String, List<Pair<ByteArray, Int>>>()\n\nfun loadKeyMaterials(context: Context, accountName: String): List<Pair<ByteArray, Int>> {\n    val result = weakCachedKeyMap.get(accountName)\n    if (!result.isNullOrEmpty()) {\n        return result\n    }\n    val keyManager = LocalKeyManager.getInstance(context)\n    val keys = keyManager.getKeysForDomain(accountName, ODLH_SECURITY_DOMAIN)\n        .ifEmpty { keyManager.getKeysForDomain(accountName, ODLH_SECURITY_DOMAIN_SHORT) }\n    val materials = keys.mapNotNull { key ->","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-core/src/main/kotlin/com/google/android/gms/semanticlocationhistory/extensions.kt#L29-L65","documentation":"requestGellerOauthToken looks up an AccountManager account of the default type matching the given accountName and throws RuntimeException(\"account is null\") if no such account exists on the device. The caller (e.g. getObfuscatedGaiaId) therefore requires a signed-in matching Google account.","triggerScenarios":"Calling getObfuscatedGaiaId / requestGellerOauthToken with an accountName string that does not exactly match any registered account of AuthConstants.DEFAULT_ACCOUNT_TYPE — account not signed in, typo, different casing, or account removed since it was cached.","commonSituations":"Semantic location history features running for an account that was signed out or removed from the device, or a stale account name persisted in app settings.","solutions":["Verify the account exists before calling: AccountManager.get(context).getAccountsByType(AuthConstants.DEFAULT_ACCOUNT_TYPE).any { it.name == accountName }","Re-query the account list instead of caching the account name across sign-out events","Trigger the account add/sign-in flow if the account is missing","Catch RuntimeException in the caller and prompt for re-authentication"],"exampleFix":"// before\nval gaiaId = context.getObfuscatedGaiaId(accountName)\n// after\nval account = AccountManager.get(context).getAccountsByType(AuthConstants.DEFAULT_ACCOUNT_TYPE).find { it.name == accountName }\nval gaiaId = if (account != null) context.getObfuscatedGaiaId(accountName) else null","handlingStrategy":"type-guard","validationCode":"val exists = AccountManager.get(context)\n    .getAccountsByType(AuthConstants.DEFAULT_ACCOUNT_TYPE)\n    .any { it.name == accountName }\nif (!exists) promptSignIn() else context.getObfuscatedGaiaId(accountName)","typeGuard":"fun Context.findAccount(accountName: String): Account? =\n    AccountManager.get(this).getAccountsByType(AuthConstants.DEFAULT_ACCOUNT_TYPE)\n        .firstOrNull { it.name == accountName }","tryCatchPattern":"try {\n    val gaiaId = context.getObfuscatedGaiaId(accountName)\n} catch (e: RuntimeException) {\n    handleMissingAccount(accountName)\n}","preventionTips":["Re-resolve accounts instead of caching account names across sessions","Listen for LOGIN_ACCOUNTS_CHANGED_ACTION to refresh cached account names","Compare account names case-sensitively as AccountManager does"],"tags":["android","account-manager","authentication"],"backgroundTag":"user-not-found","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"}