Version
- App: 2026.3.2-full
- Android: 16 (SDK 36)
- Phone: Pixel 9 Pro XL
Description
When the app has multiple servers configured and one server is unreachable, createGeofencingRequest() in LocationSensorManager.kt fails for all servers, not just the unreachable one.
Root cause
In createGeofencingRequest() (line 1099-1118), zone fetching is done per-server inside ioScope.async blocks, then collected with .awaitAll():
getEnabledServers(latestContext, zoneLocation).map { serverId ->
ioScope.async {
val configuredZones = getZones(serverId, forceRefresh = true)
// ...
}
}.awaitAll()
If getZones(serverId) throws for any server (e.g., NoUrlAvailableException because the server is unreachable, or HTTP 410 Gone because the webhook expired), awaitAll() propagates the exception. This crashes the entire function before any geofences are registered — even for servers that are perfectly healthy.
Impact
This completely breaks location tracking (both zone and background) for users with multiple servers when one server becomes unreachable. In my case:
- Server A: reachable, working correctly
- Server B: unreachable from current network, webhook returning 410 Gone
The Server B failure prevented any geofences from being registered for Server A. The device tracker was stuck at unknown for days because no location updates were ever sent.
Expected behavior
Zone fetching failures for one server should not prevent geofence registration for other servers. Each server's zones should be fetched independently, with per-server error handling.
Suggested fix
Wrap each server's zone fetch in a try/catch inside the async block, or use supervisorScope:
getEnabledServers(latestContext, zoneLocation).map { serverId ->
ioScope.async {
try {
val configuredZones = getZones(serverId, forceRefresh = true)
configuredZones.forEach {
addGeofenceToBuilder(geofencingRequestBuilder, serverId, it)
geofenceCount++
// ...
}
geofenceRegistered.add(serverId)
} catch (e: Exception) {
Timber.e(e, "Failed to fetch zones for server $serverId, skipping")
}
}
}.awaitAll()
Logs
D LocationSensorManager: Registering for zone based location updates
E LocationSensorManager: Error receiving zones from Home Assistant
E LocationSensorManager: io.homeassistant.companion.android.common.data.integration.IntegrationException: All URLs failed for get_zones
W LocationSensorManager: No zones, skipping zone based location updates
Version
Description
When the app has multiple servers configured and one server is unreachable,
createGeofencingRequest()inLocationSensorManager.ktfails for all servers, not just the unreachable one.Root cause
In
createGeofencingRequest()(line 1099-1118), zone fetching is done per-server insideioScope.asyncblocks, then collected with.awaitAll():getEnabledServers(latestContext, zoneLocation).map { serverId -> ioScope.async { val configuredZones = getZones(serverId, forceRefresh = true) // ... } }.awaitAll()If
getZones(serverId)throws for any server (e.g.,NoUrlAvailableExceptionbecause the server is unreachable, orHTTP 410 Gonebecause the webhook expired),awaitAll()propagates the exception. This crashes the entire function before any geofences are registered — even for servers that are perfectly healthy.Impact
This completely breaks location tracking (both zone and background) for users with multiple servers when one server becomes unreachable. In my case:
The Server B failure prevented any geofences from being registered for Server A. The device tracker was stuck at
unknownfor days because no location updates were ever sent.Expected behavior
Zone fetching failures for one server should not prevent geofence registration for other servers. Each server's zones should be fetched independently, with per-server error handling.
Suggested fix
Wrap each server's zone fetch in a try/catch inside the async block, or use
supervisorScope:getEnabledServers(latestContext, zoneLocation).map { serverId -> ioScope.async { try { val configuredZones = getZones(serverId, forceRefresh = true) configuredZones.forEach { addGeofenceToBuilder(geofencingRequestBuilder, serverId, it) geofenceCount++ // ... } geofenceRegistered.add(serverId) } catch (e: Exception) { Timber.e(e, "Failed to fetch zones for server $serverId, skipping") } } }.awaitAll()Logs