Quick answer: GameMaker buffer_async_save returning before finishing leaves a corrupt file? Async writes don't have transactional semantics - write to a temp file and rename on completion.

Player closes the app mid-save. Save file is partial; next launch fails to parse.

Write temp then rename

buffer_async_save(buf, "save.tmp", 0, buf_size);
// in async complete:
file_rename("save.tmp", "save.dat");

Rename is atomic on most filesystems. Partial temp files don't replace the good save.

Validate on load

Compute and store a checksum at save time. Reject loads with bad checksum; fall back to a backup.

Keep generational backups

save.dat, save.dat.1, save.dat.2. Each save rotates. Recovery from corruption becomes a one-line action.

“Saves should be transactional. Atomic rename is the cheapest transaction primitive.”

Document the save flow in the engineering wiki. New contributors will need to know exactly how the save file becomes valid; the algorithm is short but easy to break.