{"record":{"id":"3f4497fd7f17c6c5","repo":"microg/GmsCore","slug":"account-account-name-does-not-match-hosteddomai","errorCode":null,"errorMessage":"account ${account.name} does not match hostedDomainFilter=$hostedDomain","messagePattern":"account (.+?) does not match hostedDomainFilter=\\$hostedDomain","errorType":"exception","errorClass":"InvalidAccountException","httpStatus":null,"severity":"error","filePath":"play-services-core/src/main/kotlin/org/microg/gms/auth/credentials/identity/AuthorizationService.kt","lineNumber":118,"sourceCode":"    }\n\n    private suspend fun performAuthorize(request: AuthorizationRequest?): AuthorizationResult {\n        require(request?.requestedScopes?.isNotEmpty() == true) { \"requestedScopes cannot be null or empty\" }\n\n        val requestAccount = request!!.account\n        val candidate = requestAccount ?: AccountUtils.get(context).getSelectedAccount(packageName) ?: SignInConfigurationService.getDefaultAccount(context, packageName)\n        if (candidate == null || request.forceCodeForRefreshToken) {\n            return buildPendingIntentResult(request)\n        }\n\n        val account = AccountManager.get(context).getAccountsByType(AuthConstants.DEFAULT_ACCOUNT_TYPE).firstOrNull { it == candidate } ?: run {\n            AccountUtils.get(context).removeSelectedAccount(packageName)\n            return buildPendingIntentResult(request)\n        }\n\n        val hostedDomain = request.hostedDomainFilter\n        if (!hostedDomain.isNullOrEmpty() && !account.name.lowercase(Locale.ROOT).endsWith(\"@${hostedDomain.lowercase(Locale.ROOT)}\")) {\n            throw InvalidAccountException(\"account ${account.name} does not match hostedDomainFilter=$hostedDomain\")\n        }\n\n        val crossAccount = requestAccount != null && account.name != requestAccount.name\n        val options = buildSignInOptions(request, crossAccount)\n        val includeGrantedScopes = if (request.offlineAccess) \"0\" else \"1\"\n        val (accessToken, signInAccount) = performSignIn(context, packageName, options, account, false, includeGrantedScopes = includeGrantedScopes)\n        if (accessToken == null || signInAccount == null) {\n            return buildPendingIntentResult(request)\n        }\n\n        if (requestAccount != null) {\n            AccountUtils.get(context).saveSelectedAccount(packageName, requestAccount)\n        }\n\n        return AuthorizationResult(\n            signInAccount.serverAuthCode,\n            accessToken,\n            signInAccount.idToken,","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-core/src/main/kotlin/org/microg/gms/auth/credentials/identity/AuthorizationService.kt#L100-L136","documentation":"AuthorizationService.performAuthorize enforces the hostedDomainFilter from the AuthorizationRequest: the selected account's email must end with '@<hostedDomain>' (case-insensitive). If it does not, InvalidAccountException is thrown, meaning the chosen Google account is outside the Workspace domain the app requested.","triggerScenarios":"Calling AuthorizationService.authorize (via RequestAuthorization / GoogleAuthService) with a request whose hostedDomainFilter is set (e.g. 'example.com') while the user picks (or the system preselects) an account whose email does not end with @example.com.","commonSituations":"Workspace apps restricting sign-in to a company domain while a personal gmail.com account is the default account on the device; typo in the hosted domain string; domain renamed/rebranded so old accounts no longer match.","solutions":["Choose an account whose email is under the configured hosted domain before authorizing","Fix or remove the hostedDomainFilter in the AuthorizationRequest if domain restriction is not intended","Verify the domain string spelling/case in the app config","Let the user re-pick the account by clearing the selected account (AccountUtils removeSelectedAccount) and retrying authorization"],"exampleFix":"// before\nAuthorizationRequest.Builder(...).setHostedDomainFilter(\"example.com\")...\n// after — only set when the app truly requires a Workspace domain\nval builder = AuthorizationRequest.Builder(...)\nif (requireWorkspace) builder.setHostedDomainFilter(\"example.com\") else builder","handlingStrategy":"validation","validationCode":"// check the account against the filter before authorizing\nval matches = account.name.lowercase(Locale.ROOT)\n  .endsWith(\"@\" + hostedDomain.lowercase(Locale.ROOT))\nif (hostedDomain != null && !matches) {\n  // prompt user to pick a different account\n}","typeGuard":"fun Account.matchesHostedDomain(domain: String?): Boolean =\n  domain.isNullOrEmpty() || name.lowercase(Locale.ROOT).endsWith(\"@\" + domain.lowercase(Locale.ROOT))","tryCatchPattern":"try {\n  authorizationService.performAuthorize(request, account)\n} catch (e: InvalidAccountException) {\n  // account outside hostedDomainFilter — show account picker again\n}","preventionTips":["Only set hostedDomainFilter when Workspace domain restriction is actually required","Validate account email domain client-side before selecting it for authorization","Clear stored selected accounts when the domain requirement changes","Double-check domain spelling and casing in configuration"],"tags":["oauth","authorization","hosted-domain","workspace"],"backgroundTag":"invalid-argument-value","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}