diff --git a/res/values/strings.xml b/res/values/strings.xml
index 32907f5304..da2f419b43 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -737,6 +737,7 @@
     <string name="MessageDisplayHelper_bad_encrypted_message">Bad encrypted message</string>
     <string name="MessageDisplayHelper_message_encrypted_for_non_existing_session">Message encrypted for non-existing session</string>
     <string name="MessageRecord_session_restore_sent">You have sent a session restoration request to %s</string>
+    <string name="MessageRecord_session_restore_done">Secure session reset done</string>
 
     <!-- MmsMessageRecord -->
     <string name="MmsMessageRecord_bad_encrypted_mms_message">Bad encrypted MMS message</string>
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java
index 97a7364366..eeb1c3cc0a 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java
@@ -358,7 +358,7 @@ public class ConversationFragment extends Fragment
       if (messageRecord.isGroupAction() || messageRecord.isCallLog() ||
           messageRecord.isJoined() || messageRecord.isExpirationTimerUpdate() ||
           messageRecord.isEndSession() || messageRecord.isIdentityUpdate() ||
-          messageRecord.isIdentityVerified() || messageRecord.isIdentityDefault() || messageRecord.isLokiSessionRestoreSent())
+          messageRecord.isIdentityVerified() || messageRecord.isIdentityDefault() || messageRecord.isLokiSessionRestoreSent() || messageRecord.isLokiSessionRestoreDone())
       {
         actionMessage = true;
       }
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java b/src/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java
index 008d4e79f7..b7e61d34b8 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java
@@ -114,6 +114,7 @@ public class ConversationUpdateItem extends LinearLayout
     else if (messageRecord.isIdentityVerified() ||
              messageRecord.isIdentityDefault())        setIdentityVerifyUpdate(messageRecord);
     else if (messageRecord.isLokiSessionRestoreSent()) setTextMessageRecord(messageRecord);
+    else if (messageRecord.isLokiSessionRestoreDone()) setTextMessageRecord(messageRecord);
     else                                               throw new AssertionError("Neither group nor log nor joined.");
 
     if (batchSelected.contains(messageRecord)) setSelected(true);
diff --git a/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java b/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
index af3e881a29..d6e365f36c 100644
--- a/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
+++ b/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
@@ -84,6 +84,7 @@ public interface MmsSmsColumns {
 
     // Loki
     protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT = 0x01000000;
+    protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_DONE_BIT = 0x00100000;
 
     public static boolean isDraftMessageType(long type) {
       return (type & BASE_TYPE_MASK) == BASE_DRAFT_TYPE;
@@ -237,6 +238,10 @@ public interface MmsSmsColumns {
       return (type & ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT) != 0;
     }
 
+    public static boolean isLokiSessionRestoreDoneType(long type) {
+      return (type & ENCRYPTION_LOKI_SESSION_RESTORE_DONE_BIT) != 0;
+    }
+
     public static boolean isLegacyType(long type) {
       return (type & ENCRYPTION_REMOTE_LEGACY_BIT) != 0 ||
              (type & ENCRYPTION_REMOTE_BIT) != 0;
diff --git a/src/org/thoughtcrime/securesms/database/SmsDatabase.java b/src/org/thoughtcrime/securesms/database/SmsDatabase.java
index 308b948ed9..1727d5e86d 100644
--- a/src/org/thoughtcrime/securesms/database/SmsDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/SmsDatabase.java
@@ -255,6 +255,10 @@ public class SmsDatabase extends MessagingDatabase {
     updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT);
   }
 
+  public void markAsLokiSessionRestorationDone(long id) {
+    updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_LOKI_SESSION_RESTORE_DONE_BIT);
+  }
+
   public void markAsLegacyVersion(long id) {
     updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_LEGACY_BIT);
   }
diff --git a/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java b/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java
index 12be5f89a5..567f03e26b 100644
--- a/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java
@@ -107,6 +107,8 @@ public abstract class DisplayRecord {
 
   public boolean isLokiSessionRestoreSent() { return SmsDatabase.Types.isLokiSessionRestoreSentType(type); }
 
+  public boolean isLokiSessionRestoreDone() { return SmsDatabase.Types.isLokiSessionRestoreDoneType(type); }
+
   public boolean isGroupUpdate() {
     return SmsDatabase.Types.isGroupUpdate(type);
   }
diff --git a/src/org/thoughtcrime/securesms/database/model/MessageRecord.java b/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
index 1718d14451..2e54b9d65e 100644
--- a/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
@@ -180,7 +180,7 @@ public abstract class MessageRecord extends DisplayRecord {
 
   public boolean isUpdate() {
     return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
-           isEndSession()  || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() || isLokiSessionRestoreSent();
+           isEndSession()  || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() || isLokiSessionRestoreSent() || isLokiSessionRestoreDone();
   }
 
   public boolean isMediaPending() {
diff --git a/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java b/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java
index 231696af07..273bbd6c89 100644
--- a/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java
@@ -82,7 +82,9 @@ public class SmsMessageRecord extends MessageRecord {
     } else if (SmsDatabase.Types.isNoRemoteSessionType(type)) {
       return emphasisAdded(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
     } else if (isLokiSessionRestoreSent()) {
-      return emphasisAdded(context.getString(R.string.MessageRecord_session_restore_sent, recipient.toShortString()));
+      return emphasisAdded(context.getString(R.string.SmsMessageRecord_secure_session_reset));
+    } else if (isLokiSessionRestoreDone()) {
+      return emphasisAdded(context.getString(R.string.MessageRecord_session_restore_done));
     } else if (isEndSession() && isOutgoing()) {
       return emphasisAdded(context.getString(R.string.SmsMessageRecord_secure_session_reset));
     } else if (isEndSession()) {
diff --git a/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java b/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java
index 1cf2c6d328..081340fcd5 100644
--- a/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java
@@ -83,7 +83,9 @@ public class ThreadRecord extends DisplayRecord {
     } else if (SmsDatabase.Types.isNoRemoteSessionType(type)) {
       return emphasisAdded(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
     } else if (isLokiSessionRestoreSent()) {
-      return emphasisAdded(context.getString(R.string.MessageRecord_session_restore_sent, recipient.toShortString()));
+      return emphasisAdded(context.getString(R.string.SmsMessageRecord_secure_session_reset));
+    } else if (isLokiSessionRestoreDone()) {
+      return emphasisAdded(context.getString(R.string.MessageRecord_session_restore_done));
     } else if (SmsDatabase.Types.isEndSessionType(type)) {
       return emphasisAdded(context.getString(R.string.ThreadRecord_secure_session_reset));
     } else if (MmsSmsColumns.Types.isLegacyType(type)) {
diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
index 993fb49d96..aad00aa66d 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
@@ -1073,16 +1073,17 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
                                     @NonNull Optional<Long> smsMessageId, @NonNull Throwable e)
   {
     SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
+    if (SessionMetaProtocol.shouldErrorMessageShow(context, timestamp)) {
+      if (!smsMessageId.isPresent()) {
+        Optional<InsertResult> insertResult = insertPlaceholder(sender, senderDevice, timestamp);
 
-    if (!smsMessageId.isPresent()) {
-      Optional<InsertResult> insertResult = insertPlaceholder(sender, senderDevice, timestamp);
-
-      if (insertResult.isPresent()) {
-        smsDatabase.markAsDecryptFailed(insertResult.get().getMessageId());
-        messageNotifier.updateNotification(context, insertResult.get().getThreadId());
+        if (insertResult.isPresent()) {
+          smsDatabase.markAsDecryptFailed(insertResult.get().getMessageId());
+          messageNotifier.updateNotification(context, insertResult.get().getThreadId());
+        }
+      } else {
+        smsDatabase.markAsDecryptFailed(smsMessageId.get());
       }
-    } else {
-      smsDatabase.markAsDecryptFailed(smsMessageId.get());
     }
 
     // FIXME: This is a temporary patch for bad mac issues. At least with this people will be able to message again. We have to figure out the root cause of the issue though.
@@ -1100,25 +1101,26 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
       }
     }
 
-    SessionManagementProtocol.triggerSessionRestorationUI(context, sender);
+    SessionManagementProtocol.triggerSessionRestorationUI(context, sender, timestamp);
   }
 
   private void handleNoSessionMessage(@NonNull String sender, int senderDevice, long timestamp,
                                       @NonNull Optional<Long> smsMessageId)
   {
     SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
+    if (SessionMetaProtocol.shouldErrorMessageShow(context, timestamp)) {
+      if (!smsMessageId.isPresent()) {
+        Optional<InsertResult> insertResult = insertPlaceholder(sender, senderDevice, timestamp);
 
-    if (!smsMessageId.isPresent()) {
-      Optional<InsertResult> insertResult = insertPlaceholder(sender, senderDevice, timestamp);
-
-      if (insertResult.isPresent()) {
-        smsDatabase.markAsNoSession(insertResult.get().getMessageId());
-        messageNotifier.updateNotification(context, insertResult.get().getThreadId());
+        if (insertResult.isPresent()) {
+          smsDatabase.markAsNoSession(insertResult.get().getMessageId());
+          messageNotifier.updateNotification(context, insertResult.get().getThreadId());
+        }
+      } else {
+        smsDatabase.markAsNoSession(smsMessageId.get());
       }
-    } else {
-      smsDatabase.markAsNoSession(smsMessageId.get());
     }
-    SessionManagementProtocol.triggerSessionRestorationUI(context, sender);
+    SessionManagementProtocol.triggerSessionRestorationUI(context, sender, timestamp);
   }
 
   private void handleLegacyMessage(@NonNull String sender, int senderDevice, long timestamp,
diff --git a/src/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt b/src/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt
index e81f3c9fb6..d41ef58791 100644
--- a/src/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt
+++ b/src/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt
@@ -307,7 +307,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
     override fun getSessionRequestSentTimestamp(publicKey: String): Long? {
         val database = databaseHelper.readableDatabase
         return database.get(sessionRequestSentTimestampTable, "${LokiAPIDatabase.publicKey} = ?", wrap(publicKey)) { cursor ->
-            cursor.getInt(LokiAPIDatabase.timestamp)
+            cursor.getLong(LokiAPIDatabase.timestamp)
         }?.toLong()
     }
 
diff --git a/src/org/thoughtcrime/securesms/loki/protocol/SessionManagementProtocol.kt b/src/org/thoughtcrime/securesms/loki/protocol/SessionManagementProtocol.kt
index c0143a3042..4e986fcf59 100644
--- a/src/org/thoughtcrime/securesms/loki/protocol/SessionManagementProtocol.kt
+++ b/src/org/thoughtcrime/securesms/loki/protocol/SessionManagementProtocol.kt
@@ -62,7 +62,8 @@ object SessionManagementProtocol {
         val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
         val sentTimestamp = apiDB.getSessionRequestSentTimestamp(publicKey) ?: 0
         val processedTimestamp = apiDB.getSessionRequestProcessedTimestamp(publicKey) ?: 0
-        return timestamp > sentTimestamp && timestamp > processedTimestamp
+        val restorationTimestamp = TextSecurePreferences.getRestorationTime(context)
+        return timestamp > sentTimestamp && timestamp > processedTimestamp && timestamp > restorationTimestamp
     }
 
     @JvmStatic
@@ -99,10 +100,13 @@ object SessionManagementProtocol {
     }
 
     @JvmStatic
-    fun triggerSessionRestorationUI(context: Context, publicKey: String) {
+    fun triggerSessionRestorationUI(context: Context, publicKey: String, errorTimestamp: Long) {
         val masterDevicePublicKey = MultiDeviceProtocol.shared.getMasterDevice(publicKey) ?: publicKey
         val masterDeviceAsRecipient = recipient(context, masterDevicePublicKey)
         if (masterDeviceAsRecipient.isGroupRecipient) { return }
+        if (TextSecurePreferences.getRestorationTime(context) > errorTimestamp) {
+            return ApplicationContext.getInstance(context).sendSessionRequestIfNeeded(publicKey)
+        }
         val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(masterDeviceAsRecipient)
         DatabaseFactory.getLokiThreadDatabase(context).addSessionRestoreDevice(threadID, publicKey)
     }
diff --git a/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt b/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt
index 2327cbe3bb..b4a16ed505 100644
--- a/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt
+++ b/src/org/thoughtcrime/securesms/loki/protocol/SessionMetaProtocol.kt
@@ -30,6 +30,12 @@ object SessionMetaProtocol {
         return shouldIgnoreMessage
     }
 
+    @JvmStatic
+    fun shouldErrorMessageShow(context: Context, timestamp: Long): Boolean {
+        val restorationTimestamp = TextSecurePreferences.getRestorationTime(context)
+        return timestamp > restorationTimestamp
+    }
+
     @JvmStatic
     fun handleProfileUpdateIfNeeded(context: Context, content: SignalServiceContent) {
         val rawDisplayName = content.senderDisplayName.orNull() ?: return
diff --git a/src/org/thoughtcrime/securesms/loki/protocol/SessionResetImplementation.kt b/src/org/thoughtcrime/securesms/loki/protocol/SessionResetImplementation.kt
index 1c8a283125..b8e0fa8e87 100644
--- a/src/org/thoughtcrime/securesms/loki/protocol/SessionResetImplementation.kt
+++ b/src/org/thoughtcrime/securesms/loki/protocol/SessionResetImplementation.kt
@@ -2,7 +2,10 @@ package org.thoughtcrime.securesms.loki.protocol
 
 import android.content.Context
 import org.thoughtcrime.securesms.ApplicationContext
+import org.thoughtcrime.securesms.database.Address
 import org.thoughtcrime.securesms.database.DatabaseFactory
+import org.thoughtcrime.securesms.recipients.Recipient
+import org.thoughtcrime.securesms.sms.OutgoingTextMessage
 import org.whispersystems.libsignal.loki.SessionResetProtocol
 import org.whispersystems.libsignal.loki.SessionResetStatus
 import org.whispersystems.libsignal.protocol.PreKeySignalMessage
@@ -22,7 +25,14 @@ class SessionResetImplementation(private val context: Context) : SessionResetPro
             val job = NullMessageSendJob(publicKey)
             ApplicationContext.getInstance(context).jobManager.add(job)
         }
-        // TODO: Show session reset succeed message
+        val smsDB = DatabaseFactory.getSmsDatabase(context)
+        val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false)
+        val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
+        val infoMessage = OutgoingTextMessage(recipient, "", 0, 0)
+        val infoMessageID = smsDB.insertMessageOutbox(threadID, infoMessage, false, System.currentTimeMillis(), null)
+        if (infoMessageID > -1) {
+            smsDB.markAsLokiSessionRestorationDone(infoMessageID)
+        }
     }
 
     override fun validatePreKeySignalMessage(publicKey: String, message: PreKeySignalMessage) {