fix(#3993): add stale-load guard before self-heal so a superseded boot load can't wipe a healthy session (Codex CORE race)
currentSid is snapshotted before the awaited /api/session fetch; if the user clicks a healthy session while a boot-time restore is in flight and that boot load then fails non-404, _clearStuckSessionOnBoot(sid, null) would wipe the healthy session's localStorage/URL. Guard the catch block on _loadingSessionId !== sid (a newer load superseded this one) — re-arm the active stream and bail before any self-heal/DOM mutation. Protects both the non-404 and 404 inline self-heal paths. + regression test.
This commit is contained in:
@@ -921,6 +921,17 @@ async function loadSession(sid){
|
||||
data = await api(`/api/session?session_id=${encodeURIComponent(sid)}&messages=0&resolve_model=0`);
|
||||
} catch(e) {
|
||||
const _msgInner = $('msgInner');
|
||||
// Stale-load guard (Codex): a newer loadSession() may have started while this
|
||||
// request was awaiting (e.g. the user clicked a healthy session during a
|
||||
// boot-time restore). currentSid was snapshotted before the await, so without
|
||||
// this guard a failed superseded load could self-heal (wipe localStorage/URL)
|
||||
// for the session the user actually navigated to. If we no longer own the
|
||||
// load, re-arm the active session's stream and bail before any DOM mutation
|
||||
// or self-heal.
|
||||
if (_loadingSessionId !== sid) {
|
||||
_rearmActiveSessionStream();
|
||||
return;
|
||||
}
|
||||
if(_msgInner){
|
||||
if(e.status===404){
|
||||
_msgInner.innerHTML='<div style="display:flex;align-items:center;justify-content:center;height:100%;color:var(--text-muted);font-size:14px;padding:40px;text-align:center;">Session not available in web UI.</div>';
|
||||
|
||||
@@ -75,3 +75,27 @@ def test_does_not_clear_when_viewing_a_healthy_session():
|
||||
data = _run_helper("'live-session-123'")
|
||||
assert data["removed"] is False
|
||||
assert data["replaced"] is False
|
||||
|
||||
|
||||
def test_stale_load_guard_present_before_self_heal():
|
||||
"""A superseded in-flight load (a newer loadSession started during the await)
|
||||
must bail BEFORE any self-heal/DOM mutation, so a failed boot restore can't
|
||||
wipe localStorage/URL for the session the user navigated to mid-flight (Codex
|
||||
race finding). The guard re-arms the active stream and returns."""
|
||||
js = _read(SESSIONS_JS)
|
||||
# Anchor on the self-heal CALL (unique; the bare name also appears in the
|
||||
# helper's docstring), then look at the preceding window of the same
|
||||
# loadSession catch block for the stale-load guard.
|
||||
heal_idx = js.index("_clearStuckSessionOnBoot(sid, currentSid);")
|
||||
block = js[heal_idx - 2400: heal_idx + 60]
|
||||
guard = "if (_loadingSessionId !== sid) {"
|
||||
assert guard in block, "stale-load guard missing from the loadSession catch block"
|
||||
# The guard must come BEFORE the self-heal call (so a superseded load can't clear).
|
||||
assert block.index(guard) < block.index("_clearStuckSessionOnBoot(sid, currentSid);"), \
|
||||
"stale-load guard must precede _clearStuckSessionOnBoot"
|
||||
# And before the 404 inline clear too.
|
||||
assert block.index(guard) < block.index("localStorage.removeItem('hermes-webui-session')"), \
|
||||
"stale-load guard must precede the 404 inline self-heal"
|
||||
# It re-arms the active stream rather than leaving it torn down.
|
||||
guard_tail = block[block.index(guard): block.index(guard) + 120]
|
||||
assert "_rearmActiveSessionStream()" in guard_tail
|
||||
|
||||
Reference in New Issue
Block a user