Skip to content

StreamChatError: "queryChannels without an active connection" thrown unhandled during internal reconnect-recovery #2910

Description

@TheoGermain

Bug report

Describe the bug

StreamChatClient._onConnectionStatusChanged calls queryChannelsOnline() internally (unawaited by the caller) when the connection transitions from disconnected to connected, to recover previously-active channels:

https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat/lib/src/client/client.dart#L609-L623

If the connection drops again between the status flipping to connected and this internal call reaching _queryChannelsOnlineImpl's connection check, it throws an uncaught StreamChatError:

StreamChatError(message: You cannot use queryChannels without an active connection. Please call `connectUser` to connect the client.)

Because this call happens inside the SDK's own internal listener rather than in any Future chain the app awaits, application code has no way to catch it. It surfaces as an unhandled, fatal error (PlatformDispatcher.onError) in production, mostly on mobile connections with flapping connectivity (backgrounding, poor network, etc.).

To Reproduce

Hard to reproduce deterministically since it's a timing race, but reliably happens in production under flaky connectivity:

  1. App goes offline then online (or backgrounded then resumed), triggering a WS reconnect.
  2. _onConnectionStatusChanged detects connectionRecovered and calls queryChannelsOnline without awaiting the result at the call site.
  3. Connectivity drops again before the request's connection check runs.
  4. _queryChannelsOnlineImpl throws StreamChatError with no surrounding try/catch, crashing to the top-level error handler.

Expected behavior

This internal recovery call should not surface as an unhandled/fatal error to the app. Either:

  • wrap the internal await queryChannelsOnline(...) call at client.dart:619 in a try/catch that swallows/logs this specific race, or
  • have _queryChannelsOnlineImpl gracefully return/skip instead of throwing when invoked internally for reconnect-recovery purposes.

Additional context

  • stream_chat version: 10.3.0
  • Flutter 3.44.2 (stable), Dart 3.12.2
  • Seen in production on Android (various devices), ~20 occurrences / 19 users impacted in the last month for our app.
  • We've worked around it on our end by filtering this specific error out of our crash reporting, but it would be better fixed at the source since it indicates a real internal race in the reconnect-recovery flow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions