diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx
index 7f25a8e01..7634c1f51 100644
--- a/source/funkin/save/Save.hx
+++ b/source/funkin/save/Save.hx
@@ -732,6 +732,87 @@ class Save
     }
   }
 
+  public static function archiveBadSaveData(data:Dynamic):Void
+  {
+    // We want to save this somewhere so we can try to recover it for the user in the future!
+
+    final RECOVERY_SLOT_START = 1000;
+
+    writeToAvailableSlot(RECOVERY_SLOT_START, data);
+  }
+
+  public static function debug_queryBadSaveData():Void
+  {
+    final RECOVERY_SLOT_START = 1000;
+    final RECOVERY_SLOT_END = 1100;
+    var firstBadSaveData = querySlotRange(RECOVERY_SLOT_START, RECOVERY_SLOT_END);
+    if (firstBadSaveData > 0)
+    {
+      trace('[SAVE] Found bad save data in slot ${firstBadSaveData}!');
+      trace('We should look into recovery...');
+
+      trace(haxe.Json.stringify(fetchFromSlotRaw(firstBadSaveData)));
+    }
+  }
+
+  static function fetchFromSlotRaw(slot:Int):Null<Dynamic>
+  {
+    var targetSaveData = new FlxSave();
+    targetSaveData.bind('$SAVE_NAME${slot}', SAVE_PATH);
+    if (targetSaveData.isEmpty()) return null;
+    return targetSaveData.data;
+  }
+
+  static function writeToAvailableSlot(slot:Int, data:Dynamic):Void
+  {
+    trace('[SAVE] Finding slot to write data to (starting with ${slot})...');
+
+    var targetSaveData = new FlxSave();
+    targetSaveData.bind('$SAVE_NAME${slot}', SAVE_PATH);
+    while (!targetSaveData.isEmpty())
+    {
+      // Keep trying to bind to slots until we find an empty slot.
+      trace('[SAVE] Slot ${slot} is taken, continuing...');
+      slot++;
+      targetSaveData.bind('$SAVE_NAME${slot}', SAVE_PATH);
+    }
+
+    trace('[SAVE] Writing data to slot ${slot}...');
+    targetSaveData.mergeData(data, true);
+
+    trace('[SAVE] Data written to slot ${slot}!');
+  }
+
+  /**
+   * Return true if the given save slot is not empty.
+   * @param slot The slot number to check.
+   * @return Whether the slot is not empty.
+   */
+  static function querySlot(slot:Int):Bool
+  {
+    var targetSaveData = new FlxSave();
+    targetSaveData.bind('$SAVE_NAME${slot}', SAVE_PATH);
+    return !targetSaveData.isEmpty();
+  }
+
+  /**
+   * Return true if any of the slots in the given range is not empty.
+   * @param start The starting slot number to check.
+   * @param end The ending slot number to check.
+   * @return The first slot in the range that is not empty, or `-1` if none are.
+   */
+  static function querySlotRange(start:Int, end:Int):Int
+  {
+    for (i in start...end)
+    {
+      if (querySlot(i))
+      {
+        return i;
+      }
+    }
+    return -1;
+  }
+
   static function fetchLegacySaveData():Null<RawSaveData_v1_0_0>
   {
     trace("[SAVE] Checking for legacy save data...");
diff --git a/source/funkin/save/migrator/SaveDataMigrator.hx b/source/funkin/save/migrator/SaveDataMigrator.hx
index 4fa9dd6b3..b7d278cc6 100644
--- a/source/funkin/save/migrator/SaveDataMigrator.hx
+++ b/source/funkin/save/migrator/SaveDataMigrator.hx
@@ -36,6 +36,7 @@ class SaveDataMigrator
       {
         var message:String = 'Error migrating save data, expected ${Save.SAVE_DATA_VERSION}.';
         lime.app.Application.current.window.alert(message, "Save Data Failure");
+        Save.archiveBadSaveData(inputData);
         trace('[SAVE] ' + message);
         return new Save(Save.getDefault());
       }
diff --git a/source/funkin/util/VersionUtil.hx b/source/funkin/util/VersionUtil.hx
index 18d7eafa6..b84b66341 100644
--- a/source/funkin/util/VersionUtil.hx
+++ b/source/funkin/util/VersionUtil.hx
@@ -39,13 +39,16 @@ class VersionUtil
     if (thx.Types.isAnonymousObject(versionData.version))
     {
       // This is bad! versionData.version should be an array!
-      versionData.version = [versionData.version[0], versionData.version[1], versionData.version[2]];
+      trace('[SAVE] Version data repair required! (got ${versionData.version})');
+      var fixedVersionData = [versionData.version[0], versionData.version[1], versionData.version[2]];
+      versionData.version = fixedVersionData;
 
       var fixedVersion:thx.semver.Version = versionData;
       return fixedVersion;
     }
     else
     {
+      trace('[SAVE] Version data repair not required (got ${version})');
       // No need for repair.
       return version;
     }