Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

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

Chiusa
#6,616 3 commenti 1 reazione 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
50/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Tranquilla
Stack tecnologico
android, kotlin
Ambito
databases, mobile

Direzione di ricerca

Inizia da ChatClient.setUser() e segui il relativo gestore onErrorSuspend fino a disconnectSuspend(flushPersistence = true), disconnectUserSuspend(), repositoryFacade.clear() e mutableClientState.clearState(). Riproduci l’avvio a freddo offline con offlineEnabled=true e verifica che un errore di connectUser() dovuto esclusivamente alla connettività preservi i dati memorizzati nella cache e lo stato dell’utente locale; aggiungi la copertura di regressione se è possibile identificare la posizione del test pertinente.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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.
Lingua principale
Kotlin
Stelle
1.7k
Fork
320
Merge medio
1g 9h
PR unite (30g)
134

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di GetStream/stream-chat-android

Tutte le issue di GetStream/stream-chat-android

Issue simili

Altre issue su Kotlin

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.