microg/GmsCore · error · StandardIntegrityException

IntegrityErrorCode.NETWORK_ERROR

IntegrityErrorCode.NETWORK_ERROR

Error message

DroidGuard failed.

What it means

DroidGuard (Google's on-device attestation/integrity check) returned a payload beginning with the error prefix instead of a usable token, so the service cannot continue and throws IntegrityErrorCode.NETWORK_ERROR with message "DroidGuard failed.". This indicates the device-side DroidGuard verdict step failed, typically due to connectivity, device integrity, or Play Services issues.

Source

Thrown at vending-app/src/main/kotlin/com/google/android/finsky/integrityservice/IntegrityService.kt:180

                val authToken = getAuthToken(context, AUTH_TOKEN_SCOPE)
                if (TextUtils.isEmpty(authToken)) {
                    Log.w(TAG, "requestIntegrityToken: Got null auth token for type: $AUTH_TOKEN_SCOPE")
                }
                Log.d(TAG, "requestIntegrityToken authToken: $authToken")

                val droidGuardData = withContext(Dispatchers.IO) {
                    val droidGuardResultsRequest = DroidGuardResultsRequest()
                    droidGuardResultsRequest.bundle.putString("thirdPartyCallerAppPackageName", packageName)
                    Log.d(TAG, "Running DroidGuard (flow: $INTEGRITY_FLOW_NAME, data: $data)")
                    val droidGuardToken = DroidGuard.getClient(context).getResults(INTEGRITY_FLOW_NAME, data, droidGuardResultsRequest).await()
                    Log.d(TAG, "Running DroidGuard (flow: $INTEGRITY_FLOW_NAME, droidGuardToken: $droidGuardToken)")
                    Base64.decode(droidGuardToken, Base64.NO_PADDING or Base64.NO_WRAP or Base64.URL_SAFE).toByteString()
                }

                if (droidGuardData.utf8().startsWith(INTEGRITY_PREFIX_ERROR)) {
                    Log.w(TAG, "droidGuardData: ${droidGuardData.utf8()}")
                    throw StandardIntegrityException(IntegrityErrorCode.NETWORK_ERROR, "DroidGuard failed.")
                }

                val integrityRequest = IntegrityRequest(
                    params = integrityParams,
                    flowName = INTEGRITY_FLOW_NAME,
                    droidGuardTokenRaw = droidGuardData,
                    playCoreVersion = playCoreVersion,
                    playProtectDetails = PlayProtectDetails(PlayProtectState.PLAY_PROTECT_STATE_NO_PROBLEMS),
                    appAccessRiskDetailsResponse = AppAccessRiskDetailsResponse(
                        installedAppsSignalDataWrapper = InstalledAppsSignalDataWrapper("."),
                        screenCaptureSignalDataWrapper = ScreenCaptureSignalDataWrapper("."),
                        screenOverlaySignalDataWrapper = ScreenOverlaySignalDataWrapper("."),
                        accessibilityAbuseSignalDataWrapper = AccessibilityAbuseSignalDataWrapper(),
                        displayListenerMetadataWrapper = DisplayListenerMetadataWrapper(
                            lastDisplayAddedTimeDelta = makeTimestamp(SystemClock.elapsedRealtimeNanos())
                        )
                    )
                )

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Retry the request with exponential backoff — DroidGuard failures are often transient.
  2. Check network connectivity and that Google Play Services is up to date and enabled on the device.
  3. Catch IntegrityErrorCode.NETWORK_ERROR and surface a retryable state to the user rather than treating it as a policy violation.
  4. Test on a known-good device to rule out device-integrity (root/emulator) causes; escalate to Play Console support if persistent on healthy devices.

Example fix

// before
integrityManager.requestIntegrityToken(request)
// after
try {
    integrityManager.requestIntegrityToken(request)
} catch (e: StandardIntegrityException) {
    if (e.errorCode == IntegrityErrorCode.NETWORK_ERROR) {
        scheduleRetryWithBackoff() // transient DroidGuard failure
    } else throw e
}
Defensive patterns

Strategy: retry

Validate before calling

// No pre-call validation possible; check connectivity first
val cm = context.getSystemService(ConnectivityManager::class.java)
val online = cm.activeNetwork?.let { cm.getNetworkCapabilities(it)?.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) } == true

Try / catch

try {
    integrityManager.requestIntegrityToken(request)
} catch (e: StandardIntegrityException) {
    if (e.errorCode == IntegrityErrorCode.NETWORK_ERROR) {
        retryWithExponentialBackoff(maxAttempts = 3)
    } else throw e
}

Prevention

When it happens

Trigger: requestIntegrityToken where the DroidGuard result for flow INTEGRITY_FLOW_NAME decodes to UTF-8 starting with INTEGRITY_PREFIX_ERROR — i.e. DroidGuard itself reports a failure rather than returning a token.

Common situations: Device offline or flaky network during the attestation; Play Services/device issues (rooted, unlocked bootloader, unlicensed device); Google Play Services out of date or disabled; transient server-side DroidGuard failures under load.

Related errors


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