microg/GmsCore · error · IllegalArgumentException
$callingPackageName does not have google games access
Error message
$callingPackageName does not have google games access
What it means
FirstPartyGamesService is restricted to Google first-party apps: after resolving the caller it checks PackageUtils.callerHasGooglePackagePermission(GAMES) and throws IllegalArgumentException("<pkg> does not have google games access") when the caller lacks that signature-based permission. This gate keeps the first-party Play Games implementation available only to Google-signed packages.
Source
Thrown at play-services-core/src/main/kotlin/org/microg/gms/games/FirstPartyGamesService.kt:37
import com.google.android.gms.games.client.IPlayGamesService
import com.google.android.gms.games.client.PlayGamesConsistencyTokens
import org.microg.gms.BaseService
import org.microg.gms.common.Constants
import org.microg.gms.common.GmsService
import org.microg.gms.common.GooglePackagePermission
import org.microg.gms.common.PackageUtils
import org.microg.gms.utils.warnOnTransactionIssues
private const val TAG = "PlayGamesService"
private val FIRST_PARTY_PACKAGES = setOf(Constants.GMS_PACKAGE_NAME, GAMES_PACKAGE_NAME)
class FirstPartyGamesService : BaseService(TAG, GmsService.GAMES) {
override fun handleServiceRequest(callback: IGmsCallbacks, request: GetServiceRequest, service: GmsService) {
val packageName = PackageUtils.getAndCheckCallingPackageOrImpersonation(this, request.packageName)
?: throw IllegalArgumentException("Missing package name")
val callingPackageName = PackageUtils.getCallingPackage(this) ?: packageName
if (!PackageUtils.callerHasGooglePackagePermission(this, GooglePackagePermission.GAMES))
throw IllegalArgumentException("$callingPackageName does not have google games access")
if (callingPackageName !in FIRST_PARTY_PACKAGES) throw IllegalArgumentException("$callingPackageName is not first-party")
callback.onPostInitCompleteWithConnectionInfo(
CommonStatusCodes.SUCCESS,
PlayGamesServiceImpl(this, lifecycle, packageName),
ConnectionInfo()
)
}
}
class PlayGamesServiceImpl(val context: Context, val lifecycle: Lifecycle, val packageName: String) : IPlayGamesService.Stub() {
override fun getGameCollection(callbacks: IPlayGamesCallbacks?, maxResults: Int, gameCollectionType: Int, z: Boolean, forceReload: Boolean) {
Log.d(TAG, "Not yet implemented: getGameCollection($maxResults, $gameCollectionType, $z, $forceReload)")
callbacks?.onData(DataHolder.empty(CommonStatusCodes.SUCCESS))
}
override fun loadGames(callbacks: IPlayGamesCallbacks?, playerId: String?, maxResults: Int, z: Boolean, forceReload: Boolean) {
Log.d(TAG, "Not yet implemented: loadGames($playerId, $maxResults, $z, $forceReload)")View on GitHub (pinned to 157c9d86ac)
Solutions
- Bind to the regular GamesService or GamesConnectService endpoints instead of FirstPartyGamesService
- If you legitimately need first-party access, the calling package must be signed with a Google signature (not achievable for third parties)
- For microG-based clients, use the impersonation path with a properly matching signature or the non-first-party service
Defensive patterns
Strategy: fallback
Validate before calling
// caller-side check val isFirstParty = PackageUtils.callerHasGooglePackagePermission(context, GooglePackagePermission.GAMES)
Try / catch
try {
firstPartyGamesClient.connect()
} catch (e: IllegalArgumentException) {
if (e.message?.endsWith("does not have google games access") == true) {
gamesConnectClient.connect() // fall back to public endpoint
}
} Prevention
- Third-party apps must use GamesService or GamesConnectService, not FirstPartyGamesService
- Do not attempt to bind first-party endpoints from debug-signed builds
- Understand GooglePackagePermission is signature-based and cannot be granted to non-Google apps
When it happens
Trigger: Any non-Google-signed app binding to GmsService.GAMES through FirstPartyGamesService and reaching the permission check — its package name is interpolated into the message.
Common situations: A third-party game (or a modded/microG client like a custom Games client) connecting to the first-party endpoint instead of the regular GamesService/GamesConnectService; tests binding with a debug-signed app.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- $callingPackageName is not first-party
- Missing package name
- Missing package name
- Missing package name
- Service not supported:
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/aa16d2bbc9026ac0.
Report an issue: GitHub.