Error Handling

When integrating Stream, you should make sure to prepare for the following error types:

  • WebSocket connection drops
  • API Errors
  • Unhandled errors
  • Hook errors (for React and React Native)

This page shows how to handle each error type.

WebSocket connection issues

If you're watching a feed, it's important to have a WebSocket connection to receive real-time updates. The client automatically creates a WebSocket connection when connecting a user. The state of the WebSocket connection can be observed via is_ws_connection_healthy client state variable.

If the WebSocket connection is lost, the client will automatically retry restoring the connection. It's typical to display a UI indicator when the WebSocket connection is lost, to notify users that displayed data may be outdated.

import { FeedsClient } from "@stream-io/feeds-client";

const client = new FeedsClient("<API key>");
await client.connectUser({ id: "john" }, "<user token>");

// Subscribe to changes
const unsubscribe = client.state.subscribe((state) => {
  // It will return undefined if there is no connected user
  console.log(state.connected_user);
  console.log(state.is_ws_connection_healthy);
});

// Unsibscribe when you no longer need/want to receive updates
unsubscribe();

// Read current state
client.state.getLatestValue().connected_user;

If the WebSocket connection is restored, the client will automatically refetch watched state:

  • If a feed was watch-ed before the connection was lost, the feed will be refetched using getOrCreate to refresh feed metadata and latest activities
  • Reading a single activity with client.activityWithStateUpdates.get(...) is also refetched, as long as any of the feeds the activity is posted to is watch-ed. Usually you want to read a single activity when implementing an activity details page, and read the activity when loading the page, and call activity.dispose when leaving the page. Without calling dispose the activity may be refetched unnecessarily after WebSocket reconnection.

If refetching any feed/activity fails, an Unhandled error event is emitted.

API Errors

You should wrap all API calls with a try-catch block, and handle errors as you see fit (most likely you want to display an error message in your application UI). The client won't log these errors or attempt to retry failed requests.

Unhandled Errors

In rare cases the SDK will make an API call that wasn't initiated by the integrator. These are:

  • Refetching watched feeds and activities after the WebSocket connection was dropped and restored
  • Fetching own_ fields of an activity when a feeds.activity.added event is received and added to the activity list (unless enrichment options provided to getOrCreate makes this step unnecessary)

The SDK will retry these requests, but it'll eventually give up and emit an errors.unhandled event.

client.on("errors.unhandled", (event) => {
  const errorType = event.error_type;

  switch (errorType) {
    case UnhandledErrorType.ReconnectionReconciliation: {
      reconnect();
      break;
    }

    case UnhandledErrorType.FetchingOwnFieldsOnNewActivity: {
      reconnect();
      break;
    }

    default: {
      console.warn(`Unrecognized error ${errorType} has been dispatched.`);
    }
  }
});

const reconnect = async () => {
  await client.disconnectUser();
  await client.connectUser(CURRENT_USER, "<token or provider>");
};

Hook Errors

These are errors that might occur from hooks within the React or React Native SDK that do API requests (useCreateFeedsClient is one example of this). The hooks will also rethrow errors from within the render function so that they can be caught by a React ErrorBoundary in your integration.