diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py
index e5db8b2a4975a6ba0cc68fd396186d8a775aa9f5..c4dc05a862a893e0e78c06be6378d7a6c6b50062 100644
--- a/src/common/connection_handlers.py
+++ b/src/common/connection_handlers.py
@@ -977,6 +977,8 @@ class ConnectionHandlersBase:
             if keyID:
                 def decrypt_thread(encmsg, keyID, obj):
                     decmsg = self.gpg.decrypt(encmsg, keyID)
+                    decmsg = self.connection.Dispatcher.replace_non_character(
+                        decmsg)
                     # \x00 chars are not allowed in C (so in GTK)
                     obj.msgtxt = helpers.decode_string(decmsg.replace('\x00',
                         ''))
diff --git a/src/common/stanza_session.py b/src/common/stanza_session.py
index 3cceec8c6ce1894ced1b8a9955582ac96e75a717..fc1819437c776a76260308466444bf364c657b91 100644
--- a/src/common/stanza_session.py
+++ b/src/common/stanza_session.py
@@ -492,6 +492,9 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
         for child in parsed.getChildren():
             stanza.addChild(node=child)
 
+        # replace non-character unicode
+        stranza = self.conn.connection.Dispatcher.replace_non_character(stanza)
+
         return stanza
 
     def decrypt(self, ciphertext):
diff --git a/src/common/xmpp/dispatcher_nb.py b/src/common/xmpp/dispatcher_nb.py
index bdec74afdda110bed21c0e919aeb9ca0ae27936d..37020e5c644cfb9b41231e002977bb97761fd45d 100644
--- a/src/common/xmpp/dispatcher_nb.py
+++ b/src/common/xmpp/dispatcher_nb.py
@@ -197,6 +197,9 @@ class XMPPDispatcher(PlugIn):
             raise ValueError('Incorrect stream start: (%s,%s). Terminating.'
                     % (tag, ns))
 
+    def replace_non_character(self, data):
+        return re.sub(self.invalid_chars_re, u'\ufffd'.encode('utf-8'), data)
+
     def ProcessNonBlocking(self, data):
         """
         Check incoming stream for data waiting
@@ -212,7 +215,7 @@ class XMPPDispatcher(PlugIn):
         # disconnect method will never be called.
         # Is this intended?
         # also look at transports start_disconnect()
-        data = re.sub(self.invalid_chars_re, u'\ufffd'.encode('utf-8'), data)
+        data = self.replace_non_character(data)
         for handler in self._cycleHandlers:
             handler(self)
         if len(self._pendingExceptions) > 0: