diff --git a/lib/ops/user-store-ops.js b/lib/ops/user-store-ops.js
--- a/lib/ops/user-store-ops.js
+++ b/lib/ops/user-store-ops.js
@@ -2,6 +2,7 @@
 
 import { type BaseStoreOpsHandlers } from './base-ops.js';
 import type { UserInfo, UserInfos } from '../types/user-types.js';
+import { values } from '../utils/objects.js';
 
 // client types
 export type ReplaceUserOperation = {
@@ -41,6 +42,15 @@
   | RemoveUsersOperation
   | RemoveAllUsersOperation;
 
+function convertUserInfosToReplaceUserOps(
+  userInfos: UserInfos,
+): $ReadOnlyArray<UserStoreOperation> {
+  return values(userInfos).map(userInfo => ({
+    type: 'replace_user',
+    payload: userInfo,
+  }));
+}
+
 const userStoreOpsHandlers: BaseStoreOpsHandlers<
   UserInfos,
   UserStoreOperation,
@@ -79,4 +89,4 @@
   },
 };
 
-export { userStoreOpsHandlers };
+export { userStoreOpsHandlers, convertUserInfosToReplaceUserOps };
diff --git a/lib/reducers/user-reducer.js b/lib/reducers/user-reducer.js
--- a/lib/reducers/user-reducer.js
+++ b/lib/reducers/user-reducer.js
@@ -17,6 +17,10 @@
   updateUserAvatarActionTypes,
   resetUserStateActionType,
 } from '../actions/user-actions.js';
+import {
+  convertUserInfosToReplaceUserOps,
+  userStoreOpsHandlers,
+} from '../ops/user-store-ops.js';
 import { stateSyncSpecs } from '../shared/state-sync/state-sync-specs.js';
 import { updateSpecs } from '../shared/updates/update-specs.js';
 import type { BaseAction } from '../types/redux-types.js';
@@ -31,7 +35,11 @@
 } from '../types/socket-types.js';
 import { updateTypes } from '../types/update-types-enum.js';
 import { processUpdatesActionType } from '../types/update-types.js';
-import type { CurrentUserInfo, UserStore } from '../types/user-types.js';
+import type {
+  CurrentUserInfo,
+  UserInfos,
+  UserStore,
+} from '../types/user-types.js';
 import { setNewSessionActionType } from '../utils/action-utils.js';
 import { getMessageForException } from '../utils/errors.js';
 import { assertObjectsAreEqual } from '../utils/objects.js';
@@ -122,10 +130,9 @@
   return state;
 }
 
-// eslint-disable-next-line no-unused-vars
 function assertUserStoresAreEqual(
-  processedUserStore: UserStore,
-  expectedUserStore: UserStore,
+  processedUserStore: UserInfos,
+  expectedUserStore: UserInfos,
   location: string,
   onStateDifference: (message: string) => mixed,
 ) {
@@ -133,7 +140,7 @@
     assertObjectsAreEqual(
       processedUserStore,
       expectedUserStore,
-      `UserStore - ${location}`,
+      `UserInfos - ${location}`,
     );
   } catch (e) {
     console.log(
@@ -148,20 +155,33 @@
   }
 }
 
+const { processStoreOperations: processUserStoreOps } = userStoreOpsHandlers;
+
 function reduceUserInfos(
   state: UserStore,
   action: BaseAction,
-  // eslint-disable-next-line no-unused-vars
   onStateDifference: (message: string) => mixed,
 ): [UserStore, $ReadOnlyArray<ClientUserInconsistencyReportCreationRequest>] {
   if (
     action.type === joinThreadActionTypes.success ||
     action.type === newThreadActionTypes.success
   ) {
-    const newUserInfos = _keyBy(userInfo => userInfo.id)(
+    const newUserInfos: UserInfos = _keyBy(userInfo => userInfo.id)(
       action.payload.userInfos,
     );
-    const updated = { ...state.userInfos, ...newUserInfos };
+
+    const processedUserInfos: UserInfos = processUserStoreOps(
+      state.userInfos,
+      convertUserInfosToReplaceUserOps(newUserInfos),
+    );
+    const updated: UserInfos = { ...state.userInfos, ...newUserInfos };
+    assertUserStoresAreEqual(
+      processedUserInfos,
+      updated,
+      action.type,
+      onStateDifference,
+    );
+
     if (!_isEqual(state.userInfos)(updated)) {
       return [
         {