diff --git a/lib/tunnelbroker/use-peer-to-peer-message-handler.js b/lib/tunnelbroker/use-peer-to-peer-message-handler.js
--- a/lib/tunnelbroker/use-peer-to-peer-message-handler.js
+++ b/lib/tunnelbroker/use-peer-to-peer-message-handler.js
@@ -8,6 +8,7 @@
 import { removePeerUsersActionType } from '../actions/aux-user-actions.js';
 import { invalidateTunnelbrokerDeviceTokenActionType } from '../actions/tunnelbroker-actions.js';
 import { logOutActionTypes, useLogOut } from '../actions/user-actions.js';
+import { usePeerOlmSessionsCreatorContext } from '../components/peer-olm-session-creator-provider.react.js';
 import {
   useBroadcastDeviceListUpdates,
   useBroadcastAccountDeletion,
@@ -37,7 +38,11 @@
 import { getConfig } from '../utils/config.js';
 import { getContentSigningKey } from '../utils/crypto-utils.js';
 import { getMessageForException } from '../utils/errors.js';
-import { hasHigherDeviceID, olmSessionErrors } from '../utils/olm-utils.js';
+import {
+  hasHigherDeviceID,
+  OLM_SESSION_ERROR_PREFIX,
+  olmSessionErrors,
+} from '../utils/olm-utils.js';
 import { getClientMessageIDFromTunnelbrokerMessageID } from '../utils/peer-to-peer-communication-utils.js';
 import { useDispatchActionPromise } from '../utils/redux-promise-utils.js';
 import { useDispatch, useSelector } from '../utils/redux-utils.js';
@@ -173,6 +178,7 @@
 
   const handleOlmMessageToDevice = useHandleOlmMessageToDevice();
   const resendPeerToPeerMessages = useResendPeerToPeerMessages();
+  const { createOlmSessionsWithPeer } = usePeerOlmSessionsCreatorContext();
 
   return React.useCallback(
     async (message: PeerToPeerMessage, messageID: string) => {
@@ -270,17 +276,30 @@
             console.log('Failed processing Olm P2P message:', e);
           }
         } catch (e) {
-          if (e.message?.includes(olmSessionErrors.messageAlreadyDecrypted)) {
+          if (e.message?.includes(olmSessionErrors.invalidSessionVersion)) {
             console.log(
-              'Received already decrypted message from device ' +
+              'Received message decrypted with different session from ' +
                 `${message.senderInfo.deviceID}.`,
             );
-          } else {
-            console.log(
-              'Error decrypting message from device ' +
-                `${message.senderInfo.deviceID}: ${e.message}`,
-            );
+            return;
+          }
+          console.log(
+            'Error decrypting message from device ' +
+              `${message.senderInfo.deviceID}: ${e.message}`,
+          );
+
+          if (!e.message?.includes(OLM_SESSION_ERROR_PREFIX)) {
+            throw e;
           }
+
+          await createOlmSessionsWithPeer(
+            message.senderInfo.userID,
+            message.senderInfo.deviceID,
+            {
+              overwriteContentSession: true,
+            },
+          );
+          await resendPeerToPeerMessages(message.senderInfo.deviceID);
         }
       } else if (message.type === peerToPeerMessageTypes.REFRESH_KEY_REQUEST) {
         try {
@@ -375,6 +394,7 @@
     },
     [
       broadcastDeviceListUpdates,
+      createOlmSessionsWithPeer,
       dispatch,
       foreignPeerDevices,
       getAndUpdateDeviceListsForUsers,
diff --git a/lib/utils/olm-utils.js b/lib/utils/olm-utils.js
--- a/lib/utils/olm-utils.js
+++ b/lib/utils/olm-utils.js
@@ -116,17 +116,14 @@
   return { identityKeys, prekey, prekeySignature };
 }
 
+export const OLM_SESSION_ERROR_PREFIX = 'OLM_';
 const olmSessionErrors = Object.freeze({
   // Two clients send the session request to each other at the same time,
   // we choose which session to keep based on `deviceID`.
-  raceCondition: 'OLM_SESSION_CREATION_RACE_CONDITION',
+  raceCondition: `${OLM_SESSION_ERROR_PREFIX}SESSION_CREATION_RACE_CONDITION`,
   // The client received a session request with a lower session version,
   // this request can be ignored.
-  alreadyCreated: 'OLM_SESSION_ALREADY_CREATED',
-  // If using sequential decrypt this error means that message was decrypted.
-  // Otherwise, it could mean that the receiver chain advance beyond and the key
-  // to decrypt that message was discarded.
-  messageAlreadyDecrypted: 'OLM_ALREADY_DECRYPTED_OR_KEYS_SKIPPED',
+  alreadyCreated: `${OLM_SESSION_ERROR_PREFIX}SESSION_ALREADY_CREATED`,
   // Error thrown when attempting to encrypt/decrypt, indicating that
   // the session for a given deviceID is not created.
   // This definition should remain in sync with the value defined in