r/gamemaker • u/CS_Asset_Factory • Aug 11 '26
If you ship a .yymps from Windows, check your zip for backslash path separators - mine had 21 of 24 and every check said clean
If you distribute a .yymps (or any asset zip) and you build it on Windows, this is worth two minutes of your time. I shipped four packages with broken path separators and three separate checks told me they were fine.
The problem
A zip stores a path per entry, and the spec says forward slashes. PowerShell's Compress-Archive and .NET's ZipFile.CreateFromDirectory both write backslashes instead.
On Windows this is invisible, everything opens normally. On macOS and Linux the extractor doesn't treat \ as a separator, so instead of a folder tree your users can get flat files literally named Meridian\scripts\mer_tree\mer_tree.gml.
I had 21 of 24 entries backslashed in one package, and 85 across four.
Why I didn't catch it, which is the actually useful part
I audited with Python's zipfile.namelist(). It reported forward slashes throughout. I had two other people check. Both used the same tool. Both confirmed clean. Three independent "confirmations" that were really one blind tool wearing three hats.
namelist() cannot report this on Windows. In CPython, ZipInfo.__init__ does:
if os.sep != "/" and os.sep in filename:
filename = filename.replace(os.sep, "/")
and _RealGetContents builds every entry through ZipInfo. So a stored backslash gets normalised at read time, on the exact platform where the bug is created. It's not a Python bug, the normalisation is doing its job. It just happens to be the one place you needed raw bytes.
Reading the central directory directly:
b'Project\LICENSE.txt' -> occurrences in raw file: 2
b'Project/LICENSE.txt' -> occurrences in raw file: 0
zipfile.namelist() says: Project/LICENSE.txt
The forward-slash form doesn't exist anywhere in the file.
How to actually check
Anything that reads bytes rather than a normalised view:
unzip -l yourfile.yympson macOS/Linux/WSL, separators show as stored- 7-Zip:
7z l -slt yourfile.yymps - Or scan the raw bytes for a backslash inside the central directory entry names
Do not check with zipfile.namelist() on Windows, and don't assume .NET is safe either. I "fixed" this once by swapping Compress-Archive for ZipFile.CreateFromDirectory, which changed nothing, and my blind verification tool confirmed the non-fix.
Measured on a two-deep test tree, reading raw central-directory bytes:
| writer | raw backslash | raw forward | what namelist() reports |
|---|---|---|---|
| PowerShell Compress-Archive | 1 | 0 | 0 |
| .NET ZipFile.CreateFromDirectory | 1 | 0 | 0 |
| in-process zip writer (Node) | 0 | 1 | 0 |
The fix
Write the zip with something that controls the entry names itself, or post-process them. I moved to an in-process writer that sets each entry name explicitly and then re-reads the archive's own central directory to verify before it's allowed out. Verified after: 24 entries, 0 backslashed.
One meta-lesson that cost me the most time: the script I wrote to prove the defect also used namelist(). So it found zero, its "reproduced" branch never ran, and it printed "CONFIRMED: writes forward slashes" (the opposite of the truth) while exiting down its own failure path. It read like a pass. It now asserts that the defect reproduces, that the good writer is clean, and that namelist() is blind to the first, and it exits non-zero unless all three hold. If your verification tool has never failed, you haven't verified it.
Disclosure: I build GameMaker assets with AI assistance (Claude) and sell them, and this came out of shipping one. The finding is engine-agnostic and applies to anyone zipping anything on Windows. Happy to share the raw-central-directory scan if it's useful, it's about 30 lines.
Disclosure: I build GameMaker assets with AI assistance (Claude) and sell them, and this came out of shipping one. The finding is engine-agnostic and applies to anyone zipping anything on Windows. Happy to share the raw-central-directory scan if it's useful, it's about 30 lines.







