Lesson 245: Bevy Playtest Crash build_label Receipt on BUILD_RECEIPT (2026)
Direct answer: Before July playtest scale invites on Bevy 0.17 wasm, file playtest_crash_label_receipt_v1.json proving console_error_panic_hook is enabled in release wasm, a custom panic hook prints surface= + build_label=, a forced internal panic probe is captured, and child wasm_build_label_receipt_v1 from wasm boot preflight is GREEN—then promote BUILD_RECEIPT playtest_crash_label_ok. Distinct from Lesson 214 minidump symbolicate (desktop stacks) and Lesson 242 WASM heap cap (tab OOM).

Why this matters now (July 2027 Bevy wasm playtest scale)
July 2027 teams scale itch WASM cohorts the week after Q3 capstone 244 goes GREEN. Facilitators paste RuntimeError: unreachable with no build_label—engineering hotfixes summer-playtest-2027-rc0 while players still run rc1. wasm boot preflight proves first-frame tags; this lesson proves panic paths carry the same identity.
The Bevy crash log correlation preflight is the ninety-second checklist—245 is the BUILD_RECEIPT milestone. Pair Lesson 239 tag wasm_crash → this row.
Beginner path (panic hook + probe)
| Step | Action | Success check |
|---|---|---|
| 1 | Confirm child wasm boot receipt GREEN | L1 child wasm_label_pass |
| 2 | Enable console_error_panic_hook in release wasm |
L2 pass |
| 3 | Install custom panic context hook | L3 build_label= in text |
| 4 | Run internal panic probe (password itch) | L4 screenshot/log |
| 5 | Verify surface=itch_public on panic |
L5 pass |
| 6 | File receipt + BUILD_RECEIPT | crash_label_ok: true |
Time: ~58 minutes first Trunk panic wiring; ~12 minutes when hooks are pinned.
Developer path (gates L1–L6)
| Gate | Check | Fail when |
|---|---|---|
| L1 | Child wasm_build_label_receipt_v1 |
wasm_label_pass: false |
| L2 | console_error_panic_hook in release |
Silent wasm panic |
| L3 | Custom set_hook context |
Panic without build_label= |
| L4 | Forced internal panic probe | No capture filed |
| L5 | surface on panic line |
Missing itch_public / webgl_playtest |
| L6 | playtest_crash_label_receipt_v1.json |
crash_label_ok: false |
L1 — child receipt crosswalk
| Field | Child (boot) | This lesson (crash) |
|---|---|---|
| Schema | wasm_build_label_receipt_v1 |
playtest_crash_label_receipt_v1 |
| Gates | W1–W6 | L1–L6 |
| Scope | First-frame boot log | Panic console block |
| Path | release-evidence/html5/WASM_BUILD_LABEL_RECEIPT.json |
release-evidence/crash/PLAYTEST_CRASH_LABEL_RECEIPT.json |
Do not duplicate W2–W5 Trunk proof inside crash receipt—reference child path.
playtest_crash_label_receipt_v1.json
{
"schema": "playtest_crash_label_receipt_v1",
"engine": "bevy",
"bevy_version": "0.17.x",
"build_label": "summer-playtest-2027-rc1",
"surface": "itch_public",
"child_receipts": {
"wasm_build_label": "release-evidence/html5/WASM_BUILD_LABEL_RECEIPT.json"
},
"panic_probe": {
"method": "internal_key_f12",
"log_excerpt": "surface=itch_public build_label=summer-playtest-2027-rc1 panic=...",
"screenshot": "release-evidence/crash/PLAYTEST_WASM_PANIC_PROBE_2027-07-14.png"
},
"gates": {
"L1_child_wasm_boot": "pass",
"L2_console_panic_hook": "pass",
"L3_custom_context_hook": "pass",
"L4_forced_panic_probe": "pass",
"L5_surface_tag": "pass",
"L6_receipt": "pass"
},
"crash_label_ok": true,
"promotion_allowed": true
}
Pin under release-evidence/crash/PLAYTEST_CRASH_LABEL_RECEIPT.json.
BUILD_RECEIPT row (L6)
| Column | Source |
|---|---|
playtest_crash_label_ok |
crash_label_ok: true |
wasm_build_label |
Child receipt (L1) |
build_label |
Matches Lesson 201 playtest pin |
Thursday row review — Wasm crash row: panic includes build_label Y/N.
Key takeaways
- Boot receipt ≠ crash receipt—W6 GREEN does not imply L3 GREEN.
crash_symbolicate_receipt_v1(Lesson 214) is desktop minidump—do not merge schemas.- Forced panic probe must be internal-only—no public itch panic buttons.
- Tag
wasm_crashvia Lesson 239—not ad-hoc Discord strings. - Q3 capstone 244 does not include Bevy—245 is Q4 scale hardening.
- Phaser heap cap 242 is 20-minute OOM—different BUILD_RECEIPT column.
promotion_allowedon this receipt is crash path only—not full July scale gate until 253 capstone.- Pair your first Bevy 0.17 platformer blog for engine setup—not panic policy.
- Facilitators reject console pastes missing
build_label=—policy in preflight, proof in 245. - Forward: Lesson 246 Ren'Py save/language isolation (when published).
Common mistakes
- Panic hook only in debug wasm builds.
- Label
unknownon panic while boot log looks fine—rebuild Trunk env. - Merging into
crash_symbolicate_receipt_v1for wasm-only week. - Public itch page with always-on panic key.
- Chasing heap cap when console shows bounds panic—wrong tag.
Troubleshooting
| Symptom | Lane |
|---|---|
| L1 child fail | wasm boot preflight |
| Silent panic | L2 console_error_panic_hook |
No build_label= in panic |
L3 custom hook order |
| Desktop stacks only | Lesson 214 |
| Wrong depot hotfixed | Lesson 244 S9 crosswalk |
Mini exercise (55 minutes)
- Ship wasm without L3—reproduce unlabeled panic.
- Add hook; pass L4 forced probe on password itch.
- Attach child
WASM_BUILD_LABEL_RECEIPT.json. - File receipt; set BUILD_RECEIPT
playtest_crash_label_okGREEN.
Continuity — Q4 2027 July playtest scale (245–253)
| Lesson | Receipt focus |
|---|---|
| 244 | Q3 capstone (prior arc) |
| 245 (this) | Bevy wasm crash build_label |
| 246 | Ren'Py save/language |
| 253 | Q4 capstone |
Previous: Lesson 244 — Q3 summer playtest capstone
Next: Lesson 246 — Ren'Py playtest save language isolation
FAQ
Same as wasm boot preflight?
Boot = W1–W6 first frame; 245 = L1–L6 panic lines.
Same as Lesson 214?
214 = desktop minidump symbolication; 245 = browser panic text.
Same as Lesson 242?
242 = heap cap at 20 min; 245 = panic context on crash.
Need 244 before 245?
244 closes Q3 eight-pack; 245 starts Q4 scale hardening—run 244 before July invite scale.
Unlabeled wasm panics are hotfix roulette—child boot receipt, panic hook, forced probe, then playtest_crash_label_ok on BUILD_RECEIPT.