Skip to content

Fix startup when upgrading a saved v0.0.12 loadout - #275

Merged
Hona merged 1 commit into
mainfrom
work/tf2-v010-storage-upgrade
Sep 1, 2026
Merged

Hona merged 1 commit into
mainfrom
work/tf2-v010-storage-upgrade

Conversation

@Hona

@Hona Hona commented Sep 1, 2026 •

Copy link
Copy Markdown
Owner

Root cause

Reproduced the exact Unable to start TF2 / TransitionFailed screen with genuine v0.0.12 equipment output, not current-version cache under old HTML. The archived v0.0.12 worker equipped Scout item 45 and persisted its 692-byte TFEQ v1 profile; the archived application successfully restored it on reload. Navigating the same browser origin to the retained v0.1.0 package then failed.

runtime.#ensureResourceRuntime initializes the worker and restores playsrc.tf2.local-equipment.v1 before resource decoding. The 693-byte equipment restore request reaches Rust Equipment::restore. Old Demoman primary/secondary entries are 0xffffffff; equip correctly resolves these to newly available stock definitions 19/20, but the final persistence equality check compared against unnormalized empty entries and returned InvalidPersistence. The WASM update returns 0; the worker emits TransitionFailed with protocol detail 0 and no reason (the UI displays only TransitionFailed). This is a loadout migration issue, not an IndexedDB/native cache or stale configuration issue.

Fix

Normalize empty entries through the existing stock-item equip authority before the strict persistence comparison. The browser writes back only a successfully restored profile whose canonical bytes changed. No cache eviction, database deletion, settings reset, error suppression, or storage-key version bump. Unknown items, invalid slots, malformed profiles and duplicate conflicts retain their validation. Official SDK CTFPlayerInventory::GetItemInLoadout likewise resolves absent loadout items to their class base item.

Verification

  • Rust regression failed before the fix with InvalidPersistence; all 11 equipment tests pass afterward.
  • 46 focused browser equipment/storage/worker-pipeline tests pass (1,655 assertions).
  • Threaded WASM and static application build pass.
  • Headed Edge, same origin: authentic old-worker save → old application reload succeeds → retained v0.1.0 fails → fixed application reaches MainMenu. Exactly bytes 236–243 change to definitions 19 and 20; Scout item 45 and all other 684 bytes remain unchanged. No persisted cache is cleared.
  • Browser tests verify unrelated settings/storage values are untouched, unchanged profiles are not rewritten, and restore failures propagate without writing.

Before:

After:

No deployment or release is included.

Copilot AI lite review requested due to automatic review settings September 1, 2026 02:34
@Hona
Hona force-pushed the work/tf2-v010-storage-upgrade branch from 2fad112 to fbf4457 Compare September 1, 2026 02:34
@Hona

Hona commented Sep 1, 2026

Copy link
Copy Markdown
Owner Author

Storage-boundary trace: authenticated configuration/WASM generation initialization completes before Tf2EquipmentProfile.initialize() is called (apps/web/tf2/src/runtime.ts, #ensureResourceRuntime). That call is the reproduced failure: generation 0 equipment restore, before resource decoding/finalization and map/presentation cache admission. Browser settings have a separate owner and are read later during UI initialization through TF2_BROWSER_SETTINGS_STORAGE_KEY; neither their parser nor persistence format is changed. Immutable object/cache integrity checks remain unchanged. The successful fixed startup retained the same browser origin and old persisted caches; no reset or deletion was used.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new startup-path storage rewrite can throw on Storage#setItem, potentially failing initialization even when restore succeeds, so it should be made best-effort.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR fixes a TF2 equipment loadout migration bug when upgrading from a saved v0.0.12 profile by normalizing “empty” (0xffffffff) slots through the stock-item equip authority before performing strict persistence equality checks, and by persisting only when Rust normalization actually changes the canonical bytes.

Changes:

  • Normalize empty persisted entries during Rust Equipment::restore so older profiles restore successfully against newer stock definitions.
  • Add a Rust regression test covering the v0.0.12 empty Demoman primary/secondary slot upgrade scenario.
  • Add browser tests and update profile initialization to rewrite local storage only when the restored persistence bytes differ.
File summaries
File Description
games/tf2/rust/src/equipment.rs Normalizes empty persisted slots during restore and adds a regression test for legacy profile upgrades.
games/tf2/browser/tests/equipment-storage.test.ts Adds focused tests to verify only changed equipment persistence is rewritten and failures do not write.
games/tf2/browser/src/equipment/profile.ts Writes back normalized persistence only when restoration changes the stored bytes.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +36 to +39
if (saved !== null && saved !== undefined) {
const normalized = btoa(String.fromCharCode(...state.persistence))
if (normalized !== saved) this.storage?.setItem(STORAGE_KEY, normalized)
}
@Hona

Hona commented Sep 1, 2026

Copy link
Copy Markdown
Owner Author

Rebased onto current main (db3a0cac). Final local checks: 11/11 Rust equipment tests; 46/46 focused browser tests; full Bun suite 1,434 passed, 21 skipped, zero failures (38,163 assertions). Required GitHub Checks is still running; merge remains gated on its success.

@Hona
Hona force-pushed the work/tf2-v010-storage-upgrade branch from fbf4457 to c944f8e Compare September 1, 2026 02:44
@Hona
Hona merged commit dbdc45c into main Sep 1, 2026
1 check passed
@Hona
Hona deleted the work/tf2-v010-storage-upgrade branch September 1, 2026 02:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants