Skip to content

Log transient connect/transport failures as warnings in LogIfFailed#216

Merged
sierpinskid merged 1 commit into
GetStream:developfrom
harlan:fix/log-transient-connect-failures-as-warning
Jun 30, 2026
Merged

Log transient connect/transport failures as warnings in LogIfFailed#216
sierpinskid merged 1 commit into
GetStream:developfrom
harlan:fix/log-transient-connect-failures-as-warning

Conversation

@harlan

@harlan harlan commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

TaskUtils.LogIfFailed logs every faulted fire-and-forget task at error severity (Debug.LogException / Debug.LogError). The SDK uses it on its connect / reconnect / state-restore operations:

  • ConnectUserAsync(...).LogIfFailed() (reconnect path, StreamChatLowLevelClient)
  • RestoreStateLostDuringDisconnect().LogIfFailed() (StreamChatClient)
  • _websocketClient.ConnectAsync(connectionUri).LogIfFailed(_logs) (StreamChatLowLevelClient)
  • DisconnectAsync().LogIfFailed(_logs) (NativeWebSocketWrapper)

When the device is offline, these fail with connectivity/transport exceptions and get reported at error severity — flooding crash/error reporting (Sentry, Bugsnag, etc.) with handled, non-actionable noise. A representative production stack:

System.Net.Http.HttpRequestException: An error occurred while sending the request
 ---> System.Net.WebException: Error: SecureChannelFailure (Unable to read data from the transport connection: Network subsystem is down.)
 ---> System.IO.IOException: Unable to read data from the transport connection: Network subsystem is down.
 ---> System.Net.Sockets.SocketException: Network subsystem is down
   ...
  at StreamChat.Libs.Utils.<>c.<LogIfFailed>b__1_0 (Task)

These are expected, transient failures that the reconnect flow recovers from — they shouldn't be logged as exceptions.

Change

LogIfFailed (both overloads) now classifies the fault: connectivity/transport exceptions are logged via Debug.LogWarning, everything else stays Debug.LogException / Debug.LogError. A shared helper walks the AggregateException (flattened, plus each inner chain) for:

  • System.Net.Http.HttpRequestException
  • System.Net.WebException
  • System.Net.Sockets.SocketException
  • System.IO.IOException
  • TimeoutException

Genuine (non-connectivity) failures are unaffected and still surface as exceptions.

Why this shape

This is the same rationale as #213 ("Log WebSocket connection-attempt timeout as a warning, not an exception"), applied at the LogIfFailed logger. #213 covered the WS TimeoutException inside HandleConnectionFailedAsync; this covers the REST connect/restore failures that fire-and-forget through LogIfFailed and never reach that handler.

Notes

  • C# 8-compatible syntax (no or/is not patterns), fully-qualified type names so no new usings are added.
  • Changelog updated under Unreleased / Fixes.

The SDK fire-and-forgets its connect / reconnect / state-restore operations through
TaskUtils.LogIfFailed (e.g. ConnectUserAsync(...).LogIfFailed(),
RestoreStateLostDuringDisconnect().LogIfFailed(), the websocket
ConnectAsync(...).LogIfFailed(_logs)). LogIfFailed logged every faulted task via
Debug.LogException / Debug.LogError — i.e. at error severity.

When the device is offline these fail with connectivity/transport exceptions
(HttpRequestException / WebException / SocketException / IOException, and the
ConnectAsync timeout's TimeoutException). They are expected, transient, and the
reconnect flow recovers from them, so reporting them at error severity floods
crash/error reporting (Sentry, Bugsnag, etc.) with handled, non-actionable noise.

Classify those exception types and log them as warnings instead; genuine
(non-connectivity) failures still surface as exceptions. Same rationale as the
connection-attempt-timeout fix in GetStream#213, applied at the LogIfFailed logger that the
REST connect/restore paths route through.
@sierpinskid

Copy link
Copy Markdown
Member

All tests passed:
image

@sierpinskid sierpinskid merged commit a5e8545 into GetStream:develop Jun 30, 2026
0 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants