Publishing & Deployment Issues May 24, 2026

itch.io HTML5 CDN Still Serves WASM as application/octet-stream After Upload - How to Fix

Fix itch.io HTML5 CDN cache serving WASM as application/octet-stream after a successful upload. curl proof table, cache-bust query, zip layout, wasm_mime_receipt_v1.json, and multi-channel build_label alignment.

By GamineAI Team

itch.io HTML5 CDN Still Serves WASM as application/octet-stream After Upload — How to Fix

Problem: itch.io shows upload successful, your zip layout looks correct, but the live demo still white-screens or hangs at the loader. curl -I on the deployed .wasm URL returns Content-Type: application/octet-stream (or an old ETag) minutes after you replaced the build.

Who is affected now: July 2026 teams running GX.games + itch + Steam parallel HTML5 lanes. You fixed MIME once using the Godot 4.5 boot-hang guide—that article covers first-upload streaming failures. This article covers CDN edge cache and “success” uploads that never update the bytes browsers fetch.

Fastest safe fix: Copy the live .wasm URL from DevTools → run curl -I (and one full GET hash if needed) → confirm application/wasm → if fail, re-upload with versioned filename or cache-bust query on index.html → file wasm_mime_receipt_v1.json with post_upload_mime_ok: true → align build_label with GX multi-channel receipts before sharing the itch link.

Direct answer

itch’s upload UI validates your package; the CDN edge may still serve stale objects or default MIME tables until the new object propagates. Browsers use WebAssembly.instantiateStreaming, which rejects application/octet-stream. Local python -m http.server tests use fresh files on disk— they do not prove the edge URL your players hit.

Why this issue spikes in July 2026

  1. Triple HTML5 storefronts — Marketing publishes itch before MIME receipt passes.
  2. Rapid re-upload loops — Fest week replaces game.wasm without bumping cache keys.
  3. GX + itch receipt stacks14 Free GX multi-channel tools added channel rows; itch MIME became the weak lane.
  4. Boot-hang help traffic — Teams apply Godot export fixes but skip post-upload curl.
  5. Forward resource brief — July itch WASM cross-check bookmark list pairs this help when shipped.

Symptoms and search phrases

  • itch dashboard: “Upload complete.”
  • Live game: loader hang or blank canvas.
  • curl -I on CDN URL: application/octet-stream.
  • ETag / Last-Modified unchanged after re-upload.
  • Incognito still broken; hard refresh sometimes works once.
  • Works when downloading zip locally; fails on hosted URL only.
  • Console: instantiateStreaming MIME type error (same symptom, different root: edge vs first publish).

Root causes (check in order)

  1. CDN edge cache serving previous game.wasm bytes or headers.
  2. Browser cache on your test machine masking partial fixes.
  3. Wrong asset URL tested (old embed path, not latest upload slot).
  4. Zip root layoutindex.html not beside .wasm on CDN path (upload “succeeded” but paths 404).
  5. Renamed wasm in zip without updating Godot export HTML references.
  6. Parallel channel drift — itch build from yesterday; GX/Steam already promoted today (build_label mismatch in support tickets, not MIME).
  7. Threaded export without itch SharedArrayBuffer — looks like hang after MIME fix; see COOP/COEP help.

Beginner path (first 30 minutes)

Prerequisites: Published itch HTML5 build, browser with DevTools, curl installed.

  1. Open itch Play in browser → F12 → Network → reload.
  2. Click game.wasm (or your engine’s wasm name) → copy full URL.
  3. Run curl -I "<url>" — read Content-Type and ETag.
  4. If octet-stream → follow Fastest safe fix (not another Godot re-export yet).
  5. If application/wasm but still hangs → boot-hang MIME help + layout/404 checks.

Common mistake: Testing MIME on localhost or the zip on disk, not the itch CDN URL.

Fastest safe fix path

Step 1 — Post-upload proof table (CDN URL only)

curl -sI "https://your-name.itch.io/your-game/html5/game.wasm"
Header Pass Fail signal
HTTP/2 200 or HTTP/1.1 200 Yes 404 → zip layout
Content-Type: application/wasm Yes application/octet-stream
Content-Length > 0 Yes 0 or tiny → wrong file
ETag changes after re-upload Yes Same ETag → stale edge

Save output to release-evidence/02-html5/itch/curl-mime-<build_label>.txt.

PowerShell:

curl.exe -sI "https://your-name.itch.io/your-game/html5/game.wasm" | Select-String -Pattern "content-type|etag|last-modified" -CaseSensitive:$false

Step 2 — Cache-bust without guessing MIME

Option A — Versioned wasm filename (preferred for fest locks)

  1. Export to game_v2026-07-rc2.wasm (engine-specific rename in export hook or post-step script).
  2. Update index.html / Godot loader reference to match.
  3. Re-upload zip; re-run Step 1 on new URL.

Option B — Query cache-bust on loader (quick jam fix)

In index.html (or engine config), append build label to wasm fetch:

// Example pattern — adapt to your export loader
const wasmUrl = "game.wasm?v=fest-demo-2026-07-rc2";

Re-upload; verify Network tab requests include ?v=.

Option C — New itch project page

When edge cache is stubborn, publish a new HTML5 target or draft page, smoke MIME, then swap the public link.

Step 3 — Zip layout verification

CDN path must expose:

index.html
game.wasm
game.pck   (Godot) / data files per engine
*.js

Fail patterns: html5/html5/index.html double nesting; wasm only inside bin/ without loader path.

Step 4 — wasm_mime_receipt_v1.json

{
  "schema": "wasm_mime_receipt_v1",
  "checked_at_utc": "2026-05-24T23:30:00Z",
  "build_label": "fest-html5-2026-07-rc2",
  "host": "itch.io",
  "wasm_url_tested": "https://your-name.itch.io/your-game/html5/game_v2026-07-rc2.wasm",
  "curl_content_type": "application/wasm",
  "post_upload_mime_ok": true,
  "cdn_cache_bust": "versioned_filename",
  "etag_changed_after_upload": true,
  "incognito_smoke_ok": true,
  "instantiate_streaming_ok": true,
  "pass": true
}

Fail closed: post_upload_mime_ok: false blocks BUILD_RECEIPT HTML5 row promotion.

Step 5 — Multi-channel build_label alignment

When itch ships beside GX + Steam:

Channel Receipt field
itch itch_upload_ok
GX gx_upload_ok
Steam steam_depot_upload_ok
All channel_label_match: true

Use one VERSION file; see GX receipt vs Steam build_label and triple-channel channel_label_match when itch is the third surface.

Step 6 — BUILD_RECEIPT + Wednesday smoke

Add columns to BUILD_RECEIPT:

Column Example
wasm_mime_receipt pass
post_upload_mime_ok true
html5_surface itch_public

Run Wednesday smoke with curl screenshot attached—not only in-browser play on your dev machine.

Working dev path — CI gate (engine-agnostic)

# Fail CI if live itch wasm URL wrong (store URL in secret/variable)
CTYPE=$(curl -sI "$ITCH_WASM_URL" | awk -F': ' '/^[Cc]ontent-[Tt]ype:/ {print $2}' | tr -d '\r')
test "$CTYPE" = "application/wasm" || exit 1
Signal Action
MIME OK, still hang Thread/SAB, 404 on .pck, or tab-refocus OOM
MIME fail, new upload Cache-bust Step 2 before re-export
Only embed broken Parent iframe COOP; test full-page itch tab
GX works, itch fail This article; do not merge channel receipts

Verification checklist

  • [ ] curl -I on CDN wasm URL → application/wasm
  • [ ] ETag or content hash changes after re-upload
  • [ ] Incognito window boots to main scene
  • [ ] wasm_mime_receipt_v1.json pass: true
  • [ ] channel_label_match when multi-channel
  • [ ] BUILD_RECEIPT HTML5 row populated
  • [ ] Marketing link updated only after receipt pass

Prevention

  1. Never announce itch “live” on upload success alone—require curl receipt.
  2. Version wasm filenames per fest RC (game_vRC2.wasm).
  3. Pair with July itch WASM cross-check resource when published.
  4. Separate boot-hang playbook (export preset) from CDN cache playbook (this page).
  5. Log itch wasm URL in playtest_scope_map_v1.json notes for facilitator repro.

Troubleshooting

Symptom Fix
Upload OK; curl still octet-stream Cache-bust Step 2; new itch page
curl wasm OK; hang remains Boot-hang + COOP + 404 checks
Hard refresh fixes once CDN cache—version filename
MIME OK on GX, fail itch Per-channel receipt; do not assume one fix covers all
Blank screen, no wasm request index.html path wrong—zip layout

FAQ

How is this different from the Godot 4.5 boot-hang MIME help?
That guide covers export preset, zip layout, and first-publish streaming failures. This guide covers post-upload CDN headers still wrong after itch reports success.

Will itch fix MIME on their side?
Treat MIME as your gate: prove with curl, cache-bust, and receipts. Self-host mirror if policy blocks your schedule.

Does application/wasm guarantee boot?
No—threads, missing .pck, and OOM are separate helps. MIME is necessary, not sufficient.

Same receipt as GX HTML5?
Use wasm_mime_receipt_v1.json for itch MIME; gx_html5_upload_receipt_v1.json for GX upload metadata—link both under one build_label.

Related links

Prove curl -I on the CDN wasm URL after every itch upload—not the green checkmark in the uploader alone.