Quick answer: Attach the player's current save to the bug report automatically when they file it, then load that save in a debug build that can open saves from any version. Text and JSON saves attach as they are; binary saves need to be base64-encoded into a text file first. From there, compare the save with a healthy one, bisect the data, and turn the broken save into a regression test.
Some bugs cannot be reproduced from steps: they depend on forty hours of choices that left one flag set and another not. The player has the exact state that triggers the bug on their disk. Getting that file into your debugger is usually the fastest route from report to fix.
Collect the save with the report
Asking players to find and email a save file works badly: most do not know where it is, and the ones who try send the wrong slot. Attach it automatically instead, from the bug report callback. With Bugnet's SDKs the callback gives you the new report's id, and you upload the save as an attachment:
UnityBugnetSDK.Instance.BugReported += (bugId, reportNumber, title) => {
string path = SaveSystem.CurrentSlotPath; // your save system
if (File.Exists(path))
BugnetSDK.Instance.UploadAttachment(bugId, path); // text or JSON saves
};
Godot 4
Bugnet.bug_reported_id.connect(func(bug_id, _number, _title):
Bugnet.upload_attachment(bug_id, "user://saves/slot_%d.json" % SaveSystem.current_slot))
Attachments can be text, JSON, image or video files up to 10 MB, and the server checks the actual contents rather than the extension. A binary save (for example one written with BinaryWriter or FileAccess.store_var) is refused as-is, so base64-encode it into a text file first:
byte[] raw = File.ReadAllBytes(path);
byte[] text = Encoding.ASCII.GetBytes(Convert.ToBase64String(raw));
BugnetSDK.Instance.UploadAttachmentBytes(bugId, "save.b64.txt", text, "text/plain");
Base64 makes the file about a third larger, so binary saves up to about 7.5 MB fit. Decode it on your machine with base64 -d save.b64.txt > save.dat. Attachments count toward your plan's upload limit, so attach saves to player-filed reports rather than every automatic error, or only when the save is the likely culprit.
Load it safely
- Use a debug build that can load any slot from any path, through a console command or a hidden menu, so you never overwrite your own saves.
- Match the version. Check the report's game version. If your save format has changed since, run the same migration the player's game would have run, because the migration itself may be the bug.
- Keep the original. Copy the file before loading; some games rewrite the save on load.
Narrow down the cause
- Reproduce first. Load the save and follow the player's steps until the bug appears.
- Diff against a healthy save at a similar point in the game. Readable formats such as JSON make this a text diff; for binary formats, a small tool that dumps the save as text pays for itself quickly.
- Bisect the data. Reset half of the suspicious values to healthy ones and see if the bug survives. Repeat until one value or a small set remains.
- Find how it got there. The broken value is the symptom; the bug is the code that wrote it. Search for every place that writes that field.
After the fix
- Keep the save as a regression test that loads it and checks the bug no longer occurs.
- Repair existing saves. Players already in the bad state may need a migration that corrects the value on load.
- Tell the player. If they left an email, Bugnet tells them when the bug's status changes; a personal note that their save helped goes further.
Create a free Bugnet project to attach saves, logs and screenshots to player reports. For corrupted saves specifically, see how to reproduce and diagnose save corruption, and for capturing the rest of the context, capturing game state for bug reports.
Frequently asked questions
How do I get a player's save file for a bug report?
Attach it automatically when the player files the report. Bugnet's SDKs give you the new report's id in a callback, and you upload the current save as an attachment.
Can I attach binary save files to a Bugnet report?
Not as-is. Attachments must be text, JSON, image or video files, checked by their contents. Base64-encode a binary save into a text file, and decode it on your machine.
How large can an attached save file be?
Up to 10 MB per attachment. Base64 adds about a third, so a binary save of up to about 7.5 MB fits once encoded.
How do I find the cause of a bug in a save file?
Reproduce it from the save, diff the save against a healthy one at a similar point, reset suspicious values until the bug disappears, then find the code that wrote the broken value.
Should I keep player save files after fixing the bug?
Keep the ones that reproduced bugs as regression tests, with the player's permission, and delete the rest.
The player already has the exact state that breaks your game. Ask the game to send it to you.