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

  1. Choose an account whose email is under the configured hosted domain before authorizing
  2. Fix or remove the hostedDomainFilter in the AuthorizationRequest if domain restriction is not intended
  3. Verify the domain string spelling/case in the app config
  4. 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

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


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/3f4497fd7f17c6c5. Report an issue: GitHub.