microg/GmsCore · error · RuntimeException

familyResponse is null

Error message

familyResponse is null

What it means

FamilyViewModel.loadFamilyMembers throws RuntimeException("familyResponse is null") when the deferred network call for GetFamilyResponse completes but yields null, so member data models cannot be parsed. This null-guard converts an empty/failed API result into an explicit error state in the UI.

Source

Thrown at play-services-core/src/main/kotlin/com/google/android/gms/family/v2/manage/model/FamilyViewModel.kt:104

    fun loadFamilyMembers(context: Context, accountName: String, appId: String, flag: Int = FAMILY_PAGE_CONTENT_FLAG_MEMBER_LIST) {
        viewModelScope.launch {
            supervisorScope {
                runCatching {
                    _uiState.update { it.copy(isLoading = true, isError = false) }
                    val oauthToken = requestOauthToken(context, accountName, SERVICE_FAMILY_SCOPE)
                    val familyResponseDeferred = async {
                        FamilyApiClient.loadFamilyData(context, oauthToken, appId, flag)
                    }
                    val configResponseDeferred = async {
                        FamilyApiClient.loadFamilyManagementConfig(context, oauthToken, appId, false)
                    }
                    val familyResponse = familyResponseDeferred.await()
                    val configResponse = configResponseDeferred.await()
                    Log.d(TAG, "loadFamilyMembers: familyResponse: $familyResponse")
                    Log.d(TAG, "loadFamilyMembers: configResponse: $configResponse")
                    familyResponse?.parseToMemberDataModels(context, accountName, configResponse)
                        ?: throw RuntimeException("familyResponse is null")
                }.onFailure { throwable ->
                    _familyChangedStateState.value = FamilyChangedState.Error(throwable.message ?: "", 4)
                    _uiState.update { it.copy(isLoading = false, isError = true) }
                    Log.d(TAG, "loadFamilyMembers error", throwable)
                }.onSuccess { list ->
                    _uiState.update {
                        it.copy(
                            isLoading = false,
                            memberList = list,
                            currentMember = list.firstOrNull { m -> m.email == accountName } ?: MemberDataModel()
                        )
                    }
                }
            }
        }
    }

    fun loadFamilyManagementPageContent(

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Check the API call and its error channel before awaiting; surface HTTP/auth failures distinctly instead of null
  2. Handle the no-family-group case as a valid empty state rather than an error
  3. Ensure requestOauthToken succeeded and the token is valid before the family request
  4. Catch the error (onFailure already sets FamilyChangedState.Error) and offer retry / sign-in flow

Example fix

// before
val familyResponse = familyResponseDeferred.await()
familyResponse?.parseToMemberDataModels(...) ?: throw RuntimeException("familyResponse is null")
// after
val familyResponse = familyResponseDeferred.await()
val members = familyResponse?.parseToMemberDataModels(...)
if (members == null) {
    _familyChangedStateState.value = FamilyChangedState.Empty
    return@runCatching
}
Defensive patterns

Strategy: type-guard

Validate before calling

val familyResponse = familyResponseDeferred.await()
if (familyResponse == null) {
    _familyChangedStateState.value = FamilyChangedState.Empty
    return@runCatching
}

Type guard

fun <T> Deferred<T?>.awaitOrNull(): T? = try { await() } catch (e: Exception) { null }
// usage: if (familyResponseDeferred.awaitOrNull() == null) treat as empty/error

Try / catch

runCatching {
    val resp = familyResponseDeferred.await()
        ?: throw RuntimeException("familyResponse is null")
}.onFailure { t -> showFamilyError(t) }

Prevention

When it happens

Trigger: The family members API call returns a null body — e.g. the account has no family group, the server returned an empty/error response, or the client wrapper maps failures to null instead of throwing.

Common situations: Opening family management for an account with no family set up, expired oauth token causing an empty response, or backend outage returning null payloads.

Understand the failure class

Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.

Related errors


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