Corrupted save data in iOS

My app has a level editor and saves levels using MessagePack in the persistent data directory. I got a bug report from an iOS user that their level had been corrupted. When I opened the file in a hex editor, it was only 78 bytes (typical files are ~50 KB) and it looked nothing like the messagepack format. Here’s a screenshot of the data:

7002701--827723--hex.png

This doesn’t resemble the file format of my app at all. It doesn’t seem to be a truncated section of a file either. The save code always writes an m byte before calling messagepack, which doesn’t appear here.

The weirdest part is at the end of the file where it has the filename in ascii. The file save code never writes the filename to the file itself, so I have no idea how it got there. That tells me something really strange is going on, beyond the save code just crashing, but I don’t know I could diagnose this.
Any idea what’s going on here? I’m completely stuck.

Here’s part of the file save code, it just relies on messagepack, but this shows that there’s no way the file name could end up in the file.

var worldObject = new MessagePackObject(world);

using (FileStream fileStream = File.Create(filePath))
{
    fileStream.WriteByte((byte)'m');
    var packer = Packer.Create(fileStream, PackerCompatibilityOptions.None);
    worldObject.PackToMessage(packer, null);
}

Wow, that is weird. That does seem like perhaps something else overwrote this file, or the loader attempted to load a file that wasn’t one of your save files.

The latter seems more possible, especially if your “find level files” code is promiscuous and could consider other files for loading, such as if you have the level files sprinkled in a general folder, and then do a “find me all files” type of deal.

Another thing is that the file above is some kind of “resource fork” file, perhaps something you’re never supposed to see, a meta file that the OS might use that somehow got opened by your app. I remember back in the dark old days of MacOS they wrote all kinds of weird meta file crud, and since this contains a bunch of random data, plus the filename, that sorta smells like it is at least related to the actual savefile.

That would make sense, but the file seemingly got corrupted while the user was in the middle of editing it. According to the report the file stopped working when they tapped the Play button to playtest the level, which saves the file and reloads in the “game” scene. The editor and game load the file from the same place, and they had previously been switching between edit/play without issue, so something happened in the middle.

I had been thinking about some kind of meta file. I really don’t know much about how iOS works. I have a post build script set up which configures the app so the files are visible in the iOS Files app. Maybe iOS is managing that somehow? Something to do with iCloud? I don’t know where to start, maybe this belongs in the iOS forum.

First thing I would do is make an app event to report such an issue happening. That way you can tell if it’s happening to half of your users or just this one guy.

Good idea, I will also add a backup system.

1 Like

Oh interesting, good idea, never thought about that… I guess you could always write each game twice (or more?), if they’re only 50k or something, and then if one fails, use the other. Another thing could be to age-out previous saves, keep a few stacked up. 50k is so tiny in today’s 512gb phones!

The solution I settled on was to write to a temporary file, and if everything goes well, copy to the main file with File.Replace (which automatically makes a backup). I don’t use any kind of analytics, but I did add better exception handling and error messages to the save function. Now it’ll actually show a stack trace so I’ll have something to go on.

1 Like