microg/GmsCore · error · IllegalStateException
Network URL required
Error message
Network URL required
What it means
RemoteHandleImpl performs DroidGuard flows against a remote network server whose URL is read lazily from DroidGuardPreferences.getNetworkServerUrl(context). When no server URL is configured, the url property getter throws IllegalStateException('Network URL required') as soon as any operation needs the URL. The remote handle is useless without a configured endpoint, so the library fails fast instead of issuing a request to null.
Source
Thrown at play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/RemoteHandleImpl.kt:24
package org.microg.gms.droidguard.core
import android.content.Context
import android.net.Uri
import android.util.Base64
import com.google.android.gms.droidguard.internal.DroidGuardInitReply
import com.google.android.gms.droidguard.internal.DroidGuardResultsRequest
import com.google.android.gms.droidguard.internal.IDroidGuardHandle
import android.util.Log
import java.net.HttpURLConnection
import java.net.URL
private const val TAG = "RemoteGuardImpl"
class RemoteHandleImpl(private val context: Context, private val packageName: String) : IDroidGuardHandle.Stub() {
private var flow: String? = null
private var request: DroidGuardResultsRequest? = null
private val url: String
get() = DroidGuardPreferences.getNetworkServerUrl(context) ?: throw IllegalStateException("Network URL required")
override fun init(flow: String?) {
Log.d(TAG, "init($flow)")
this.flow = flow
}
override fun snapshot(map: Map<Any?, Any?>?): ByteArray {
Log.d(TAG, "snapshot($map)")
val paramsMap = mutableMapOf("flow" to flow, "source" to packageName)
for (key in request?.bundle?.keySet().orEmpty()) {
request?.bundle?.getString(key)?.let { paramsMap["x-request-$key"] = it }
}
val params = paramsMap.map { Uri.encode(it.key) + "=" + Uri.encode(it.value) }.joinToString("&")
val connection = URL("$url?$params").openConnection() as HttpURLConnection
val payload = map.orEmpty().map { Uri.encode(it.key as String) + "=" + Uri.encode(it.value as String) }.joinToString("&")
Log.d(TAG, "POST ${connection.url}: $payload")
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
connection.requestMethod = "POST"View on GitHub (pinned to 157c9d86ac)
Solutions
- Configure the DroidGuard network server URL in microG settings (or via the DroidGuardPreferences setter) before using RemoteHandleImpl
- Check DroidGuardPreferences.getNetworkServerUrl(context) for null before constructing/using RemoteHandleImpl and choose a local handle instead
- Catch IllegalStateException around handle usage and prompt the user to configure the server URL
- If the deployment is local-only, stop instantiating RemoteHandleImpl and use NetworkHandleProxyFactory paths exclusively
Example fix
// before
val handle = RemoteHandleImpl(context, packageName)
handle.init(flow) // throws if no URL configured
// after
val serverUrl = DroidGuardPreferences.getNetworkServerUrl(context)
requireNotNull(serverUrl) { "Configure a DroidGuard network server URL first" }
val handle = RemoteHandleImpl(context, packageName)
handle.init(flow) Defensive patterns
Strategy: validation
Validate before calling
val serverUrl = DroidGuardPreferences.getNetworkServerUrl(context)
if (serverUrl == null) {
configureServerUrlOrDefault() // or use a local handle
} else {
RemoteHandleImpl(context, packageName).init(flow)
} Try / catch
try {
remoteHandle.init(flow)
} catch (e: IllegalStateException) {
promptUserToConfigureDroidGuardServer()
} Prevention
- Configure the network server URL before instantiating RemoteHandleImpl
- Persist the setting so microG data resets don't silently drop it
- For local-only deployments, never construct the remote handle
When it happens
Trigger: Creating a RemoteHandleImpl(context, packageName) and calling init/sendReport/etc. on an install where DroidGuardPreferences.getNetworkServerUrl(context) returns null — i.e. no DroidGuard network server URL has ever been set in preferences.
Common situations: Users who disabled or never configured the DroidGuard network server in microG settings; resetting microG data wipes the configured URL; deployments using only local DroidGuard attempting a remote handle; fork builds missing default server URL configuration.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- DroidGuard should not be available locally
- Signature invalid
- IntegrityErrorCode.NETWORK_ERROR
- Access denied, missing google package permission for
- Required caller information missing
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/73e439af3baa1beb.
Report an issue: GitHub.