microg/GmsCore · error · InvalidAccountException
account ${account.name} does not match hostedDomainFilter=$h
Error message
account ${account.name} does not match hostedDomainFilter=$hostedDomain What it means
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.
Source
Thrown at play-services-core/src/main/kotlin/org/microg/gms/auth/credentials/identity/AuthorizationService.kt:118
}
private suspend fun performAuthorize(request: AuthorizationRequest?): AuthorizationResult {
require(request?.requestedScopes?.isNotEmpty() == true) { "requestedScopes cannot be null or empty" }
val requestAccount = request!!.account
val candidate = requestAccount ?: AccountUtils.get(context).getSelectedAccount(packageName) ?: SignInConfigurationService.getDefaultAccount(context, packageName)
if (candidate == null || request.forceCodeForRefreshToken) {
return buildPendingIntentResult(request)
}
val account = AccountManager.get(context).getAccountsByType(AuthConstants.DEFAULT_ACCOUNT_TYPE).firstOrNull { it == candidate } ?: run {
AccountUtils.get(context).removeSelectedAccount(packageName)
return buildPendingIntentResult(request)
}
val hostedDomain = request.hostedDomainFilter
if (!hostedDomain.isNullOrEmpty() && !account.name.lowercase(Locale.ROOT).endsWith("@${hostedDomain.lowercase(Locale.ROOT)}")) {
throw InvalidAccountException("account ${account.name} does not match hostedDomainFilter=$hostedDomain")
}
val crossAccount = requestAccount != null && account.name != requestAccount.name
val options = buildSignInOptions(request, crossAccount)
val includeGrantedScopes = if (request.offlineAccess) "0" else "1"
val (accessToken, signInAccount) = performSignIn(context, packageName, options, account, false, includeGrantedScopes = includeGrantedScopes)
if (accessToken == null || signInAccount == null) {
return buildPendingIntentResult(request)
}
if (requestAccount != null) {
AccountUtils.get(context).saveSelectedAccount(packageName, requestAccount)
}
return AuthorizationResult(
signInAccount.serverAuthCode,
accessToken,
signInAccount.idToken,View on GitHub (pinned to 157c9d86ac)
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
Example fix
// before
AuthorizationRequest.Builder(...).setHostedDomainFilter("example.com")...
// after — only set when the app truly requires a Workspace domain
val builder = AuthorizationRequest.Builder(...)
if (requireWorkspace) builder.setHostedDomainFilter("example.com") else builder Defensive patterns
Strategy: validation
Validate before calling
// check the account against the filter before authorizing
val matches = account.name.lowercase(Locale.ROOT)
.endsWith("@" + hostedDomain.lowercase(Locale.ROOT))
if (hostedDomain != null && !matches) {
// prompt user to pick a different account
} Type guard
fun Account.matchesHostedDomain(domain: String?): Boolean =
domain.isNullOrEmpty() || name.lowercase(Locale.ROOT).endsWith("@" + domain.lowercase(Locale.ROOT)) Try / catch
try {
authorizationService.performAuthorize(request, account)
} catch (e: InvalidAccountException) {
// account outside hostedDomainFilter — show account picker again
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Missing required properties: scopes
- Missing required properties: account
- client not admin, yet tried to enable work authenticator
- client not admin, yet tried to add work account
- oauthToken is null
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/3f4497fd7f17c6c5.
Report an issue: GitHub.