microg/GmsCore · error · RuntimeException

No checkin available

Error message

No checkin available

What it means

Registration gate in PushRegisterService.ensureCheckinIsUpToDate: no valid check-in exists (lastCheckin missing or older than MAX_VALID_CHECKIN_AGE and the refresh attempt returned no data), so the device is unknown to the GCM backend.

Source

Thrown at play-services-core/src/main/kotlin/org/microg/gms/gcm/PushRegisterService.kt:50

private suspend fun ensureCheckinIsUpToDate(context: Context) {
    if (!CheckinPreferences.isEnabled(context)) throw RuntimeException("Checkin disabled")
    val lastCheckin = LastCheckinInfo.read(context).lastCheckin
    if (lastCheckin < System.currentTimeMillis() - CheckinService.MAX_VALID_CHECKIN_AGE) {
        val resultData: Bundle = suspendCoroutine { continuation ->
            val intent = Intent(context, CheckinService::class.java)
            val continued = AtomicBoolean(false)
            intent.putExtra(CheckinService.EXTRA_RESULT_RECEIVER, object : ResultReceiver(null) {
                override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
                    if (continued.compareAndSet(false, true)) continuation.resume(resultData ?: Bundle.EMPTY)
                }
            })
            ForegroundServiceContext(context).startService(intent)
            Handler().postDelayed({
                if (continued.compareAndSet(false, true)) continuation.resume(Bundle.EMPTY)
            }, 10000L)
        }
        if (resultData.getLong(CheckinService.EXTRA_NEW_CHECKIN_TIME, 0L) + lastCheckin == 0L) {
            throw RuntimeException("No checkin available")
        }
    }
}

suspend fun ensureAppRegistrationAllowed(context: Context, database: GcmDatabase, packageName: String) {
    if (!GcmPrefs.get(context).isEnabled) throw RuntimeException("GCM disabled")
    val app = database.getApp(packageName)
    if (app == null && GcmPrefs.get(context).confirmNewApps) {
        val accepted: Boolean = suspendCoroutine { continuation ->
            val i = Intent(context, AskPushPermission::class.java)
            i.putExtra(AskPushPermission.EXTRA_REQUESTED_PACKAGE, packageName)
            i.putExtra(AskPushPermission.EXTRA_RESULT_RECEIVER, object : ResultReceiver(null) {
                override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
                    continuation.resume(resultCode == Activity.RESULT_OK)
                }
            })
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Retry after check-in completes — ensure check-in succeeds (network, enabled) before registering
  2. Report ERROR_SERVICE_NOT_AVAILABLE to the app when no checkin is obtainable
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at play-services-core/src/main/kotlin/org/microg/gms/gcm/PushRegisterService.kt:50 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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