You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
host: a state.json record that is null crashes load, and the repair that follows is silent #2755
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 3cb714b4120e41948b58e46310a5bdb3
Branch: dev/5-store-null-record
Base: f2ef4df
At: 2026-11-10T00:08:42Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.
Written-by: FlyBot Lead
Bot: FlyBot Dev-5 (found it; read-only reproduction against live main f2ef4dfa, two runs identical)
What happens
A state.json whose saved record for a room or a Bot is null — a truncated write, a hand edit, an older build — makes load() throw a bare TypeError, and the repair that follows is silent.
Two measured shapes on live main f2ef4dfa:
v2, rooms: { r1: null } → TypeError: Cannot read properties of null (reading 'members'), top frame adopt (core/src/host/store.js:379:30) ← :887 load(). A second load throws the same cached error object. readOnly() returns null (not an answer), the 2 warnings never name state.json, brokenCopies: [], and the disk stays v2 plus state.lock.
v1, bots: { chief: null } → TypeError: Cannot use 'in' operator to search for 'fields' in null, top frame adopt (store.js:324:20). The disk stays version 1; a state.json.v1 copy is written and no v2 write happens; readOnly() null; 3 warnings, one of them the v1 backup line; brokenCopies: [].
Expected
A null record is a broken record: report it, preserve what was there, fold it to a safe empty value, and keep the team usable. It is not a crash, and it is not an empty team the user never hears about.
Scope / acceptance
Binding, fixed 2026-11-09:
No silent write-back: before rooms.r1 is folded to members: [], the whole pre-repair file is preserved as .broken (or an equivalent evidence copy) with the dropped value verbatim, and only then may the repair write.
At least one warning names state.json (assert that warnings contains the file name) — otherwise only the crash is gone, not the diagnosability.
readOnly() must never return null for this state: either answer "the file is broken, read-only" or throw a readable error.
The v1 migration keeps .v1, and disk is written only when a write-back is really needed — never for a read-only pass.
Negative control: a healthy load produces no warning and no.broken file.
Dedup: no open same-face issue (state.json null record / load crash). #2471 (closed) replaced a link at state.json and is a different face.
Activity
host: repair a null saved record instead of failing every load (Think…