diff --git a/src/jamidht/connectionmanager.cpp b/src/jamidht/connectionmanager.cpp
index 5d6707df0e31c1e0476f6fbf920c13f206267852..355e67b54ef4a6e8cda73f9620f7bde154e7a73d 100644
--- a/src/jamidht/connectionmanager.cpp
+++ b/src/jamidht/connectionmanager.cpp
@@ -429,7 +429,7 @@ ConnectionManager::Impl::onDhtConnected(const std::string& deviceId)
         [w=weak()](PeerConnectionRequest&& req) {
             auto shared = w.lock();
             if (!shared) return false;
-            if (shared->account.isMessageTreated(req.id)) {
+            if (shared->account.isMessageTreated(to_hex_string(req.id))) {
                 // Message already treated. Just ignore
                 return true;
             }
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index 60afdca9f37dd44cf9a293e7d9573b37264a1262..d9086cc1ec1e808bd6e00f6ba7a66e6f29105982 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -1976,8 +1976,9 @@ JamiAccount::doRegister_()
         dht_->listen<dht::ImMessage>(
             inboxDeviceKey,
             [this,inboxDeviceKey](dht::ImMessage&& v) {
-                if (!setMessageTreated(v.id)) return true;
-                accountManager_->onPeerMessage(v.from, dhtPublicInCalls_, [this, v, inboxDeviceKey](const std::shared_ptr<dht::crypto::Certificate>&,
+                auto msgId = to_hex_string(v.id);
+                if (isMessageTreated(msgId)) return true;
+                accountManager_->onPeerMessage(v.from, dhtPublicInCalls_, [this, v, inboxDeviceKey, msgId](const std::shared_ptr<dht::crypto::Certificate>&,
                                                                         const dht::InfoHash& peer_account)
                 {
                     auto now = clock::to_time_t(clock::now());
@@ -1987,7 +1988,7 @@ JamiAccount::doRegister_()
                     }
                     std::map<std::string, std::string> payloads = {{datatype,
                                                                    utf8_make_valid(v.msg)}};
-                    onTextMessage(std::to_string(v.id), peer_account.toString(), payloads);
+                    onTextMessage(msgId, peer_account.toString(), payloads);
                     JAMI_DBG() << "Sending message confirmation " << v.id;
                     dht_->putEncrypted(inboxDeviceKey,
                               v.from,
@@ -2013,19 +2014,6 @@ JamiAccount::doRegister_()
     }
 }
 
-bool
-JamiAccount::setMessageTreated(const dht::Value::Id& id)
-{
-    {
-        std::lock_guard<std::mutex> lock(messageMutex_);
-        auto res = treatedMessages_.insert(id);
-        if (!res.second)
-            return false;
-    }
-    saveTreatedMessages();
-    return true;
-}
-
 void
 JamiAccount::onTextMessage(const std::string& id, const std::string& from,
                               const std::map<std::string, std::string>& payloads)
@@ -2288,7 +2276,13 @@ void
 JamiAccount::loadTreatedMessages()
 {
     std::lock_guard<std::mutex> lock(messageMutex_);
-    treatedMessages_ = loadIdList(cachePath_+DIR_SEPARATOR_STR "treatedMessages");
+    auto path = cachePath_+DIR_SEPARATOR_STR "treatedMessages";
+    treatedMessages_ = loadIdList<std::string>(path);
+    if (treatedMessages_.empty()) {
+        auto messages = loadIdList(path);
+        for (const auto& m : messages)
+            treatedMessages_.emplace(to_hex_string(m));
+    }
 }
 
 void
@@ -2299,16 +2293,16 @@ JamiAccount::saveTreatedMessages() const
             auto& this_ = *sthis;
             std::lock_guard<std::mutex> lock(this_.messageMutex_);
             fileutils::check_dir(this_.cachePath_.c_str());
-            saveIdList(this_.cachePath_+DIR_SEPARATOR_STR "treatedMessages", this_.treatedMessages_);
+            saveIdList<std::string>(this_.cachePath_+DIR_SEPARATOR_STR "treatedMessages", this_.treatedMessages_);
         }
     });
 }
 
 bool
-JamiAccount::isMessageTreated(unsigned int id)
+JamiAccount::isMessageTreated(const std::string& id)
 {
     std::lock_guard<std::mutex> lock(messageMutex_);
-    auto res = treatedMessages_.insert(id);
+    auto res = treatedMessages_.emplace(id);
     if (res.second) {
         saveTreatedMessages();
         return false;
@@ -2766,7 +2760,6 @@ JamiAccount::sendTextMessage(const std::string& to, const std::map<std::string,
             messageEngine_.onMessageSent(to, token, false);
             continue;
         }
-        auto content = payloads.begin()->second;
         im::fillPJSIPMessageBody(*tdata, payloads);
 
         // Because pjsip_endpt_send_request can take quite some time, move it in a io thread to avoid to block
@@ -2858,7 +2851,7 @@ JamiAccount::sendTextMessage(const std::string& to, const std::map<std::string,
                 JAMI_DBG() << "[Account " << getAccountID() << "] [message " << token << "] Received text message reply";
 
                 // add treated message
-                auto res = treatedMessages_.insert(msg.id);
+                auto res = treatedMessages_.emplace(to_hex_string(msg.id));
                 if (!res.second)
                     return true;
             }
diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h
index 7793344258a7b169872334b252a6ac39dcfeafbb..3d7a47d952f480b626510f2a8cc55ba630b52d22 100644
--- a/src/jamidht/jamiaccount.h
+++ b/src/jamidht/jamiaccount.h
@@ -271,12 +271,6 @@ public:
     std::shared_ptr<SIPCall>
     newIncomingCall(const std::string& from, const std::map<std::string, std::string>& details = {}, const std::shared_ptr<SipTransport>& sipTr = nullptr) override;
 
-    /**
-     * Mark message as treated
-     * @return false if the message was already treated
-     */
-    bool setMessageTreated(const dht::Value::Id& id);
-
     void onTextMessage(const std::string& id, const std::string& from, const std::map<std::string, std::string>& payloads) override;
 
     virtual bool isTlsEnabled() const override {
@@ -369,10 +363,9 @@ public:
 
     std::vector<std::string> publicAddresses();
 
-
     /// \return true if the given DHT message identifier has been treated
     /// \note if message has not been treated yet this method store this id and returns true at further calls
-    bool isMessageTreated(unsigned int id) ;
+    bool isMessageTreated(const std::string& id);
 
     std::shared_ptr<dht::DhtRunner> dht() { return dht_; }
 
@@ -596,7 +589,7 @@ private:
 
     mutable std::mutex messageMutex_ {};
     std::map<dht::Value::Id, PendingMessage> sentMessages_;
-    std::set<dht::Value::Id> treatedMessages_ {};
+    std::set<std::string> treatedMessages_ {};
 
     std::string ringDeviceName_ {};
     std::string idPath_ {};
diff --git a/src/jamidht/p2p.cpp b/src/jamidht/p2p.cpp
index 03002bea8757e21526d6b8ac98917cf1f3a7adaa..a4982717aa1a5663aaac9e800a3e1b8eedbc0e17 100644
--- a/src/jamidht/p2p.cpp
+++ b/src/jamidht/p2p.cpp
@@ -1000,7 +1000,7 @@ DhtPeerConnector::onDhtConnected(const std::string& device_id)
         [this](PeerConnectionMsg&& msg) {
             if (msg.from == pimpl_->account.dht()->getId())
                 return true;
-            if (!pimpl_->account.isMessageTreated(msg.id)) {
+            if (!pimpl_->account.isMessageTreated(to_hex_string(msg.id))) {
                 if (msg.isRequest()) {
                     // TODO: filter-out request from non trusted peer
                     pimpl_->ctrl << makeMsg<CtrlMsgType::DHT_REQUEST>(std::move(msg));
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index 8ce1cb8ef55f2d47adfe5a37732133c58468012b..c9d0c76f7a0860d878e91fe8b604e19ad54dfd01 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -260,12 +260,14 @@ transaction_request_cb(pjsip_rx_data *rdata)
                 if (msgId)
                     id = std::string(msgId->hvalue.ptr, msgId->hvalue.slen);
 
-                try {
-                    // Mark message as treated
-                    auto acc = std::dynamic_pointer_cast<JamiAccount>(account);
-                    if (acc && !id.empty() && !acc->setMessageTreated(std::stol(id)))
-                        return PJ_FALSE;
-                } catch (...) {}
+                if (not id.empty()) {
+                    try {
+                        // Mark message as treated
+                        auto acc = std::dynamic_pointer_cast<JamiAccount>(account);
+                        if (acc and acc->isMessageTreated(id))
+                            return PJ_FALSE;
+                    } catch (...) {}
+                }
                 account->onTextMessage(id, peerNumber, payloads);
             }
             return PJ_FALSE;
diff --git a/src/string_utils.cpp b/src/string_utils.cpp
index 2626e25f5c0e4617c29288c4f6a18db0027725d2..4313ed18d52a0f8c3e6d52a404829e338b3dd618 100644
--- a/src/string_utils.cpp
+++ b/src/string_utils.cpp
@@ -20,11 +20,14 @@
  */
 
 #include "string_utils.h"
+
 #include <sstream>
 #include <cctype>
 #include <algorithm>
 #include <ostream>
+#include <iomanip>
 #include <stdexcept>
+#include <ios>
 #ifdef _WIN32
 #include <windows.h>
 #include <oleauto.h>
@@ -76,6 +79,23 @@ to_string(double value)
     return {buf, (size_t)len};
 }
 
+std::string
+to_hex_string(uint64_t id) {
+    std::ostringstream ss;
+    ss << std::hex << std::setfill('0') << std::setw(16) << id;
+    return ss.str();
+}
+
+uint64_t
+from_hex_string(const std::string& str) {
+    std::istringstream ss(str);
+    ss >> std::hex;
+    uint64_t id;
+    if (!(ss >> id))
+        throw std::invalid_argument("Can't parse id: " + str);
+    return id;
+}
+
 std::string
 trim(const std::string &s)
 {
diff --git a/src/string_utils.h b/src/string_utils.h
index ca9b64c06457efdf8bc46610cdff8a4840b809ad..ff21e3e1ffe47b663051e47bf49e533280f66c19 100644
--- a/src/string_utils.h
+++ b/src/string_utils.h
@@ -29,8 +29,8 @@
 
 namespace jami {
 
-constexpr static const char* TRUE_STR = "true";
-constexpr static const char* FALSE_STR = "false";
+constexpr static const char TRUE_STR[] = "true";
+constexpr static const char FALSE_STR[] = "false";
 
 constexpr static const char*
 bool_to_str(bool b) noexcept
@@ -45,6 +45,9 @@ std::wstring to_wstring(const std::string& str, int codePage = CP_UTF8);
 std::string to_string(const std::wstring& wstr, int codePage = CP_UTF8);
 #endif
 
+std::string to_hex_string(uint64_t id);
+uint64_t from_hex_string(const std::string& str);
+
 static inline int
 stoi(const std::string& str)
 {