diff --git a/VERSION b/VERSION
index d4c4950a..0c00f610 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.3.9
+1.3.10
diff --git a/loader/src/hooks/SaveFileFix.cpp b/loader/src/hooks/SaveFileFix.cpp
index 2ed63e25..45b220b8 100644
--- a/loader/src/hooks/SaveFileFix.cpp
+++ b/loader/src/hooks/SaveFileFix.cpp
@@ -5,6 +5,17 @@
 using namespace geode::prelude;
 
 #include <Geode/cocos/support/base64.h>
+#include "../loader/LoaderImpl.hpp"
+
+void panic(std::string reason) {
+    LoaderImpl::get()->platformMessageBox("Critical", fmt::format(
+        "Your save file failed to load (reason: {})\n"
+        "As to not lose all of your data, the game will now abort.\n"
+        "Please backup your save files and try opening the game again, it might work.\n"
+        "Please contact the Geode Team about this", reason
+    ));
+    std::abort();
+}
 
 // This function is well known for crashing on certain save files,
 // causing the game to crash at startup, known as the infamous save file bug.
@@ -14,23 +25,26 @@ using namespace geode::prelude;
 // 
 // To fix this, we just rewrite the function.
 gd::string decompressString2(unsigned char* data, bool decrypt, int size, int decryptionKey) {
-    if (data == nullptr || size == 0 || *data == 0) {
+    log::debug("decompressString2 data={} size={}", reinterpret_cast<const void*>(data), size);
+    if (data == nullptr || size == 0) {
         return {};
     }
 
+    std::vector<unsigned char> copiedData(data, data + size);
     if (decrypt) {
         for (int i = 0; i < size; i++) {
-            data[i] ^= decryptionKey;
+            copiedData[i] ^= decryptionKey;
         }
     }
 
     // TODO: maybe not use cocos's base64 and inflateMemory..
 
     unsigned char* out = nullptr;
-    auto const decodedSize = cocos2d::base64Decode(data, size, &out);
+    auto const decodedSize = cocos2d::base64Decode(copiedData.data(), size, &out);
     std::unique_ptr<unsigned char> b64decoded { out };
 
     if (decodedSize <= 0) {
+        panic(fmt::format("base64 (size={}) (data={} size={})", decodedSize, reinterpret_cast<const void*>(data), size));
         return {};
     }
 
@@ -40,6 +54,7 @@ gd::string decompressString2(unsigned char* data, bool decrypt, int size, int de
     std::unique_ptr<unsigned char> inflated { out };
 
     if (inflatedSize <= 0) {
+        panic(fmt::format("inflate (size={}) (data={} size={})", inflatedSize, reinterpret_cast<const void*>(data), size));
         return {};
     }