Defold Steam Desktop Save Root Outside Collection Map After Export - How to Fix
Problem: Your Defold game passes in the Editor, but the Steam desktop build loses progress. Players quit after a checkpoint and relaunch to a fresh run. You documented collection_map_v1.json, yet saves appear under a preview or old project title folder—not the path your audit promised.
Who is affected now: Teams shipping May–October 2026 fest demos after the Defold Steam collection save audit tutorial. The failure only shows in packaged builds: Editor play mode masks wrong sys.save keys, renamed [project] title, or bootstrap collections that differ from retail.
Fastest safe fix: Run the packaged D2 save test (not Editor), print sys.get_save_file once in a dev bundle, reconcile game.project title with save_root_map_v1.json, align collection_map_v1.json bootstrap with game.project, migrate one-time copies for existing testers, and set save_root_match: true in defold_steam_audit_receipt_v1.json before SteamPipe upload.
Direct answer
Progress is not “lost”—it is usually written elsewhere. Defold resolves save file locations from project identity (title/version) and your sys.save key strings. A Steam depot built after a title rename, a fest branch that still loads a debug bootstrap collection, or duplicate save modules (debug vs retail) makes retail players write to a folder QA never checked. Fix the documented map and the actual bundle together; Editor-only tests do not count.
Why this issue spikes in 2026
- Defold Steam desktop demos joined the fest cluster beside GDevelop and GameMaker one-evening pipelines.
- Teams audit collections (D1) but skip packaged save path proof (D2).
- Branch promotion copies binaries without re-running save maps—same failure mode as save-slot label mismatch.
- Playtest and fest surfaces diverge—see playtest isolation.
Pair with 12 Free Defold GDevelop Ren'Py save-path audit resources and October Next Fest metadata checklist after save gates pass.
Symptoms and search phrases
- Save works in Editor; Steam build always starts fresh.
- Two save files on disk—one updates during QA, players use the other.
- Path contains old game title after rebrand for fest.
collection_map_v1.jsonsays/main/main.collectionbut bundle loads/debug/bootstrap.collection.- Playtest branch OK; fest_public branch resets progress.
sys.savereturnstruebutsys.loadreturnsnil(key mismatch).
Root causes (check in order)
[project] titlechanged — save directory derived from title still matches old folder on disk.- Different
sys.savekeys between save and load (typo, debug key in retail). - Bootstrap collection mismatch — gameplay collection never runs save module you tested in Editor.
- Hardcoded absolute paths in Lua (forbidden in maps; grep the bundle).
- Debug define enables alternate
save_service_debug.luain one profile only. - Wrong Steam depot promoted (playtest binary with fest
build_label). - Testing Editor instead of zipped Bundle → Desktop output.
Fastest safe fix path
Step 1 — Lock collection map to game.project
Open game.project:
[bootstrap]
main_collection = /main/main.collection
Compare to collection_map_v1.json:
{
"schema": "collection_map_v1",
"main_collection": "/main/main.collection",
"bootstrap": [
{ "collection": "/main/main.collection", "role": "retail_entry" }
],
"excluded_from_retail": ["/debug/debug_overlay.collection"]
}
Pass: main_collection strings match byte-for-byte.
Fail: Retail loads debug collection first → saves never run in shipped path.
Step 2 — Document and verify save root (save_root_map_v1.json)
{
"schema": "save_root_map_v1",
"project_title": "YourFestDemo2026",
"slots": [
{
"slot_id": "demo_progress",
"api": "sys.save",
"key": "/demo_save_v1",
"expected_relative": "verified in packaged build only"
}
],
"save_format_version": 1
}
Packaged-only probe (temporary dev bundle, remove prints before retail):
local path = sys.get_save_file("/demo_save_v1", "")
print("SAVE_PATH_PROBE", path)
Run the bundled .exe, not Editor. Record the printed path in the map’s verified_path_note.
Step 3 — Single save module contract
Use one save_service.lua (see beginner audit). Ban second keys like /debug_save in retail:
function M.save_state(state)
state._version = 1
return sys.save("/demo_save_v1", state)
end
Grep project for sys.save:
rg "sys\.save" assets/ game/
Every call must use the same key as save_root_map_v1.json.
Step 4 — D2 round-trip on packaged build
- Delete files at probed path (document before/after).
- Launch Steam build or local bundle—not Editor.
- Reach checkpoint; confirm log
sys.saveOK. - Quit process completely.
- Relaunch; checkpoint must persist.
- Confirm only one new file under expected root.
Step 5 — One-time migration for existing testers
If QA already saved under old title folder:
# Example — adjust paths from SAVE_PATH_PROBE logs
Copy-Item -Force `
"$env:USERPROFILE\AppData\Local\OldTitle\save.dat" `
"$env:USERPROFILE\AppData\Local\YourFestDemo2026\save.dat"
Ship release notes: “First launch after patch may reset if you were on pre-0.3 playtest—intentional.”
Step 6 — Receipt gate before fest upload
{
"schema": "defold_steam_audit_receipt_v1",
"build_label": "df-nextfest-2026-05-24-rc1",
"gates": {
"D1_collection_map": "pass",
"D2_save_root": "pass",
"D5_save_roundtrip": "pass"
},
"save_root_match": true,
"main_collection": "/main/main.collection",
"documented_save_key": "/demo_save_v1"
}
Attach beside BUILD_RECEIPT with save_path column matching save_root_map_v1.json.
Verification checklist
- [ ]
collection_mapmatchesgame.projectbootstrap. - [ ] Packaged probe path logged and matches map.
- [ ] D2 round-trip passes twice on clean Windows user or VM.
- [ ] No
sys.saveto debug keys in retail profile. - [ ]
save_root_match: truein audit receipt. - [ ] Wednesday smoke S4–S6 run on installed Steam build.
Prevention
- Run full five-gate audit per
build_id—not only D1. - Treat save maps as BUILD_RECEIPT columns on demo and main branches.
- Never promote fest branch until save-path resource list byte-match smoke passes.
- Separate playtest vs fest saves per playtest scope map.
- Pin Defold version in receipt when
game.projectformat shifts.
Troubleshooting
| Symptom | Fix |
|---|---|
| Save path shows old title | Rename back or migrate files; update project.title once, rebuild bundle |
| Two keys in grep | Delete debug key from retail; single save_service |
| Load nil, save true | Key typo between save/load functions |
| Works local zip, fails Steam | Wrong depot/branch promoted; verify build_label in-game |
| Collection proxy never loads | D1 fail—fix bootstrap before save logic |
FAQ
Does Defold use Steam Cloud for demos?
Only if you implement it—default sys.save is local. Align store FAQ with local-only claims.
Is this the same as GDevelop preview path?
Parallel discipline—see GDevelop save-path freeze; engine APIs differ.
Do collections affect save file location?
Collections affect which script runs sys.save, not the OS path directly—wrong bootstrap feels like “wrong save root.”
Editor vs bundle?
Editor is invalid for D2. Always bundle Desktop → Windows (or your target) per Defold save manual.
Related links
- Your First Defold Steam Desktop Collection and Save Audit (2026)
- 12 Free Defold GDevelop Ren'Py Save-Path Audit Resources
- Mismatched Save Slot Labels After Branch Promotion
- Wednesday Demo Build Smoke Ritual
- Defold — Save and load
- Defold — Building blocks (collections)
Prove saves on the Steam-installed exe—the Editor is not your fest demo.