Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

connectUser() flushes the offline cache on a plain connectivity failure (offlineEnabled=true)

Open
#6,616 3 comments 1 reaction 0 assignees View on GitHub

Maintainers usually reply within 2 days

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
50/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Quiet
Tech stack
android, kotlin
Domain
databases, mobile

Research direction

Start in ChatClient.setUser(), tracing its onErrorSuspend handler into disconnectSuspend(flushPersistence = true), disconnectUserSuspend(), repositoryFacade.clear(), and mutableClientState.clearState(). Reproduce the cold offline launch with offlineEnabled=true and verify that a connectivity-only connectUser() failure preserves cached data and local user state; add regression coverage if the relevant test location can be identified.

Written by the indexing model from the issue text.

Description

Describe the bug

A failed connectUser() (e.g. device is offline) triggers ChatClient.setUser()'s internal .onErrorSuspend { disconnectSuspend(flushPersistence = true) } handler, which wipes the client's offline Room cache via disconnectUserSuspend(flushPersistence = true) -> repositoryFacade.clear() and resets mutableClientState.clearState(). This happens on every failed connectUser() call, including a plain connectivity failure — not just auth errors — so a cold app launch while offline destroys the exact offline cache that ChatClientConfig(offlineEnabled = true) is meant to preserve for a returning, previously-authenticated user.

This directly contradicts the Offline Support guide, which frames flushPersistence = true as something a caller explicitly opts into (e.g. on logout), not a side effect of a failed reconnect — and the Handling User Connection guide, which explicitly says: "Make sure your implementation handles a missing network without recording it as a fatal error" — implying a connectUser() failure due to missing network is an expected, non-fatal occurrence, yet its side effect (wiping the offline cache) isn't documented anywhere.

SDK version

  • 7.6.0 and 7.7.0 (confirmed on both by reading the actual stream-chat-android-client sources for each version; 7.7.0's changelog doesn't mention a related fix, and re-testing on-device against 7.7.0 reproduces the same behavior)

To Reproduce

  1. Sign in successfully with ChatClient.Builder(apiKey, context).config(ChatClientConfig(offlineEnabled = true)).build(), connectUser(...), and browse channels while online so the offline cache is populated.
  2. Fully close the app (kill the process).
  3. Put the device in airplane mode / disconnect all networks.
  4. Cold-launch the app again and call connectUser(...) for the same user with no timeoutMilliseconds (or any value) — it resolves as Result.Failure since the socket can't connect.
  5. Observe: ChannelsScreen/ChannelListViewModel for this client now has an empty/perpetually-loading channel list, getCurrentUser() returns null, and the client's offline database has been cleared — even though step 1 successfully cached channels for this exact user.

Traced root cause (in io.getstream.chat.android.client.ChatClient, 7.6.0/7.7.0 sources):

private suspend fun setUser(...): Result<ConnectionData> {
    ...
    return when {
        ...
        userState is UserState.NotSet -> {
            mutableClientState.setUser(user)
            initializeClientWithUser(user, cacheableTokenProvider, isAnonymous)
            userStateService.onSetUser(user, isAnonymous)
            chatSocket.connectUser(user, isAnonymous)
            mutableClientState.setInitializationState(InitializationState.COMPLETE)
            waitFirstConnection(timeoutMilliseconds) // <- resolves Result.Failure offline, no timeout given
        }
        ...
    }.onErrorSuspend {
        disconnectSuspend(flushPersistence = true) // <- runs on ANY Result.Failure, including pure connectivity failure
    }
}

private suspend fun disconnectUserSuspend(flushPersistence: Boolean) {
    ...
    if (flushPersistence) {
        repositoryFacade.clear()       // wipes the offline Room cache
        userCredentialStorage.clear()
    }
    ...
    mutableClientState.clearState()    // getCurrentUser() becomes null again
    ...
}

Expected behavior

A connectUser() failure caused purely by lack of connectivity should not flush the offline persistence layer or clear the client's local user state — the whole point of offlineEnabled = true is that a previously-authenticated user can browse cached channels/messages without a live connection. At minimum, this destructive side effect should be documented, or ideally scoped to real auth/credential errors rather than every Result.Failure (including plain network-unreachable cases).

Workaround we're using in the meantime

Checking device connectivity (our own ConnectivityManager-backed monitor) before calling connectUser() at all, and skipping the call entirely when known-offline — this avoids triggering the destructive path, at the cost of not restoring the previously-connected user's session (and thus not showing cached channels) on that specific cold-offline launch.

Additional context

  • Related: #6009 ("Switching user cause ChannelScreen goes in an infinite loop and no chats are shown") describes the same downstream symptom (ChannelsScreen stuck/empty after a disconnect(flushPersistence = true)), triggered by an explicit switchUser() call rather than an implicit connectivity failure — but the underlying "post-flush, channel list never recovers" behavior looks like the same class of issue.
  • Happy to provide a minimal repro project if useful.
Dominant language
Kotlin
Stars
1.7k
Forks
319
Avg merge
1d 19h
Merged PRs (30d)
73

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from GetStream/stream-chat-android

All issues in GetStream/stream-chat-android

Similar issues

More Kotlin issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.