diff --git a/include/mtx/events_impl.hpp b/include/mtx/events_impl.hpp
index 4d204989c5029c10a6aae5d496d75f74db4bad87..e8e3a6fe10fe51c18ddfff3f1ed81384886830e0 100644
--- a/include/mtx/events_impl.hpp
+++ b/include/mtx/events_impl.hpp
@@ -54,9 +54,18 @@ from_json(const nlohmann::json &obj, Event<Content> &event)
         event.content = {};
     }
 
-    event.type   = getEventType(obj.at("type").get<std::string>());
+    auto type = obj.at("type").get<std::string>();
+    if (type.size() > 255) {
+        throw std::out_of_range("Type exceeds 255 bytes");
+    }
+    event.type = getEventType(type);
+
     event.sender = obj.value("sender", "");
 
+    if (event.sender.size() > 255) {
+        throw std::out_of_range("Sender exceeds 255 bytes");
+    }
+
     if constexpr (std::is_same_v<Unknown, Content>)
         event.content.type = obj.at("type").get<std::string>();
 }
@@ -135,6 +144,10 @@ from_json(const nlohmann::json &obj, StrippedEvent<Content> &event)
     from_json(obj, base);
 
     event.state_key = obj.at("state_key").get<std::string>();
+
+    if (event.state_key.size() > 255) {
+        throw std::out_of_range("State key exceeds 255 bytes");
+    }
 }
 
 template<class Content>
@@ -154,13 +167,22 @@ from_json(const nlohmann::json &obj, RoomEvent<Content> &event)
     Event<Content> &base = event;
     from_json(obj, base);
 
-    event.event_id         = obj.at("event_id").get<std::string>();
+    event.event_id = obj.at("event_id").get<std::string>();
+
+    if (event.event_id.size() > 255) {
+        throw std::out_of_range("Event id exceeds 255 bytes");
+    }
+
     event.origin_server_ts = obj.at("origin_server_ts").get<uint64_t>();
 
     // SPEC_BUG: Not present in the state array returned by /sync.
     if (obj.find("room_id") != obj.end())
         event.room_id = obj.at("room_id").get<std::string>();
 
+    if (event.room_id.size() > 255) {
+        throw std::out_of_range("Room id exceeds 255 bytes");
+    }
+
     if (obj.find("unsigned") != obj.end())
         event.unsigned_data = obj.at("unsigned").get<UnsignedData>();
 }
@@ -198,6 +220,10 @@ from_json(const nlohmann::json &obj, StateEvent<Content> &event)
     from_json(obj, base);
 
     event.state_key = obj.at("state_key").get<std::string>();
+
+    if (event.state_key.size() > 255) {
+        throw std::out_of_range("State key exceeds 255 bytes");
+    }
 }
 
 template<class Content>
@@ -261,6 +287,10 @@ from_json(const nlohmann::json &obj, EphemeralEvent<Content> &event)
 
     if (obj.contains("room_id"))
         event.room_id = obj.at("room_id").get<std::string>();
+
+    if (event.room_id.size() > 255) {
+        throw std::out_of_range("Room id exceeds 255 bytes");
+    }
 }
 
 }
diff --git a/lib/structs/responses/common.cpp b/lib/structs/responses/common.cpp
index bee5228cafd87d0b4473bcc925a9d90dad68eb73..79a0f4fa26f1ed50869cf4d7316310fdc65c0fbe 100644
--- a/lib/structs/responses/common.cpp
+++ b/lib/structs/responses/common.cpp
@@ -198,7 +198,7 @@ parse_room_account_data_events(
             case events::EventType::ImagePackInRoom:
                 continue;
             }
-        } catch (json::exception &err) {
+        } catch (std::exception &err) {
             log_error(err, e);
         }
     }
@@ -506,7 +506,7 @@ parse_timeline_events(const json &events,
             case events::EventType::Dummy:
                 continue;
             }
-        } catch (json::exception &err) {
+        } catch (std::exception &err) {
             log_error(err, e);
         }
     }
@@ -604,7 +604,7 @@ parse_device_events(const json &events,
             default:
                 continue;
             }
-        } catch (json::exception &err) {
+        } catch (std::exception &err) {
             log_error(err, e);
         }
     }
@@ -779,7 +779,7 @@ parse_state_events(const json &events,
             case events::EventType::Dummy:
                 continue;
             }
-        } catch (json::exception &err) {
+        } catch (std::exception &err) {
             log_error(err, e);
         }
     }
@@ -942,7 +942,7 @@ parse_stripped_events(const json &events,
             case events::EventType::Dummy:
                 continue;
             }
-        } catch (json::exception &err) {
+        } catch (std::exception &err) {
             log_error(err, e);
         }
     }
@@ -976,7 +976,7 @@ parse_ephemeral_events(const json &events,
             default:
                 continue;
             }
-        } catch (json::exception &err) {
+        } catch (std::exception &err) {
             utils::log_error(err, e);
         }
     }
diff --git a/lib/structs/responses/sync.cpp b/lib/structs/responses/sync.cpp
index 347c764a1aee676254a29193a569d2f7a49268b5..cc086e0465b718d4a1d70d7d6e2391b7935b7dc0 100644
--- a/lib/structs/responses/sync.cpp
+++ b/lib/structs/responses/sync.cpp
@@ -5,6 +5,7 @@
 
 #include <nlohmann/json.hpp>
 
+#include <algorithm>
 #include <variant>
 
 using json = nlohmann::json;
@@ -157,11 +158,38 @@ from_json(const json &obj, Rooms &rooms)
 void
 from_json(const json &obj, DeviceLists &device_lists)
 {
-    if (obj.count("changed") != 0)
+    if (obj.count("changed") != 0) {
         device_lists.changed = obj.at("changed").get<std::vector<std::string>>();
 
-    if (obj.count("left") != 0)
+        device_lists.changed.erase(
+          std::remove_if(device_lists.changed.begin(),
+                         device_lists.changed.end(),
+                         [](const std::string &user) {
+                             if (user.size() > 255) {
+                                 mtx::utils::log::log()->warn(
+                                   "Invalid userid in device list changed.");
+                                 return true;
+                             } else
+                                 return false;
+                         }),
+          device_lists.changed.end());
+    }
+
+    if (obj.count("left") != 0) {
         device_lists.left = obj.at("left").get<std::vector<std::string>>();
+
+        device_lists.left.erase(std::remove_if(device_lists.left.begin(),
+                                               device_lists.left.end(),
+                                               [](const std::string &user) {
+                                                   if (user.size() > 255) {
+                                                       mtx::utils::log::log()->warn(
+                                                         "Invalid userid in device list left.");
+                                                       return true;
+                                                   } else
+                                                       return false;
+                                               }),
+                                device_lists.left.end());
+    }
 }
 
 void
@@ -193,10 +221,17 @@ from_json(const json &obj, Sync &response)
         response.device_unused_fallback_key_types = fallback_keys->get<std::vector<std::string>>();
 
     if (obj.count("presence") != 0 && obj.at("presence").contains("events")) {
-        response.presence =
-          obj.at("presence")
-            .at("events")
-            .get<std::vector<mtx::events::Event<mtx::events::presence::Presence>>>();
+        const auto &events = obj.at("presence").at("events");
+        response.presence.reserve(events.size());
+        for (const auto &e : events) {
+            try {
+                response.presence.push_back(
+                  e.get<mtx::events::Event<mtx::events::presence::Presence>>());
+            } catch (std::exception &ex) {
+                mtx::utils::log::log()->warn(
+                  "Error parsing presence event: {}, {}", ex.what(), e.dump(2));
+            }
+        }
     }
 
     if (obj.count("account_data") != 0) {