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
A minimal Vue 3.5.42 harness that mirrors our production structure (keep-alive-cached chat view + streaming message list + Teleport + rapid route switches). Important: so far we have been unable to trigger the crash inside this harness (≈7,500 route switches in headless Chrome/Edge + ≈6,000 switches in Electron 44, all without crash). The crash is reliably reproduced in our real Electron app (8+ occurrences today, see "Steps to reproduce" and the production stack traces below). We keep the harness public and will update it as soon as we find a minimal trigger — we are submitting this now because the production evidence is precise and the failure is severe (whole renderer tree corruption → forced page reload).
Steps to reproduce
In a production Electron app (Windows 10 22H2, Chromium 152):
Layout: <router-view> wrapped in <keep-alive :include="['ChatView','OfficeView']">. Route components are imported synchronously (no async components in the kept-alive tree — the 使用keepalive+suspense缓存asyncsetup组件时切换过快就会报错null of parentNode #5993 workaround is already in place).
Open the chat page and send a message. The client optimistically inserts a user bubble and a streaming assistant bubble (temporary negative ids -1, -2), then applies streaming content/tool events which patch the message list multiple times per second.
While streaming is still in progress, navigate to another route (ChatView is deactivated and moved into the keep-alive cache), then quickly navigate back (activate).
The crash fires ~1–2 s after the second activation. Reproduced consistently (8+ times today; timestamps 15:30, 16:00, 16:15, 16:34, 17:00).
Runtime capture at crash time:
CRASH CONTEXT: route=#/chat || activeId=1877 || generating=[1877]
|| storeMsgIds=[-1|-2] // optimistic bubbles, ids not yet backfilled
|| keepalive=[activate@t; deactivate@t+3s; activate@t+9s]
|| msgListInDoc=false || domRows=0 // message DOM not even mounted
|| chatPageRoots=1
Notes:
The message DOM is not mounted yet (msgListInDoc=false, domRows=0) while the store already holds the two bubbles — the failing patch targets a subtree whose el is already null during the keep-alive move (activate → move from cache container to active container) racing with the async message-load re-render triggered from onActivated.
onActivated triggers an async message reload that replaces the messages array and re-renders the list; this is the "async inner render" racing the keep-alive move.
What is expected?
Switching routes while a kept-alive page (or any descendant) is mid-render/mid-stream must not corrupt the component tree. No crash, no forced reload.
What is actually happening?
TypeError: Cannot read properties of null (reading 'parentNode')
at remove (runtime-dom)
at patchKeyedChildren // keyed diff unmount path
at componentUpdateFn
at updateComponent
at processComponent
at patch
at patchBlockChildren
immediately followed by:
TypeError: Cannot destructure property 'bum' of '...' as it is null.
Component stack at crash: ChatView > KeepAlive > RouterView.
After the first error, our self-healing re-render hits the same corrupted nodes and crashes again; the app escalates to a full page reload (visible white flash + loss of in-flight UI state for the user; backend persistence is unaffected).
No <transition> around <keep-alive> (avoids the 3.5.x emptyPlaceholder issue).
All v-for keys are stable (unique ids per message/segment — not array indexes), so the keyed diff is not being confused by id backfilling.
Teleport overlays use :disabled instead of v-if unmounting; onDeactivated closes all floating layers.
The crash still occurs 100% of the time in the real app under the sequence above, and the msgListInDoc=false / domRows=0 capture rules out message-key instability: the failing patch targets a detached/null-el subtree during the keep-alive activate move racing with the async re-render scheduled by onActivated.
If useful I can attach the full production electron.log excerpts (8 occurrences, identical stack) and a stripped-down version of the real component tree.
Vue version
3.5.42 (reproduced on 3.5.42; also present in 3.5.35–3.5.41 per our sessions)
Link to minimal reproduction
https://github.com/etjson/vue-keepalive-repro
A minimal Vue 3.5.42 harness that mirrors our production structure (keep-alive-cached chat view + streaming message list + Teleport + rapid route switches). Important: so far we have been unable to trigger the crash inside this harness (≈7,500 route switches in headless Chrome/Edge + ≈6,000 switches in Electron 44, all without crash). The crash is reliably reproduced in our real Electron app (8+ occurrences today, see "Steps to reproduce" and the production stack traces below). We keep the harness public and will update it as soon as we find a minimal trigger — we are submitting this now because the production evidence is precise and the failure is severe (whole renderer tree corruption → forced page reload).
Steps to reproduce
In a production Electron app (Windows 10 22H2, Chromium 152):
<router-view>wrapped in<keep-alive :include="['ChatView','OfficeView']">. Route components are imported synchronously (no async components in the kept-alive tree — the 使用keepalive+suspense缓存asyncsetup组件时切换过快就会报错null of parentNode #5993 workaround is already in place).-1,-2), then applies streaming content/tool events which patch the message list multiple times per second.Runtime capture at crash time:
Notes:
msgListInDoc=false,domRows=0) while the store already holds the two bubbles — the failing patch targets a subtree whoseelis already null during the keep-alive move (activate → move from cache container to active container) racing with the async message-load re-render triggered fromonActivated.onActivatedtriggers an async message reload that replaces the messages array and re-renders the list; this is the "async inner render" racing the keep-alive move.What is expected?
Switching routes while a kept-alive page (or any descendant) is mid-render/mid-stream must not corrupt the component tree. No crash, no forced reload.
What is actually happening?
immediately followed by:
app.config.errorHandleras "Unhandled error during execution of scheduler flush" (runtime-core, https://vuejs.org/error-reference/#runtime-15).ChatView > KeepAlive > RouterView.System Info
System: OS: Windows 10 10.0.19045 CPU: (20) x64 Intel(R) Core(TM) i9-10850K CPU @ 3.60GHz Memory: 12.92 GB / 31.88 GB Binaries: Node: 22.20.0 npm: 10.9.3 Yarn: 1.22.22 pnpm: 11.5.2 Browsers: Chrome: 152.0.7977.75 Edge: Chromium (152.0.4191.53) npmPackages: vue: ^3.5.42 => 3.5.42Renderer: Electron (Chromium 152). Production app bundle is a Vite build (no SSR, no Suspense).
Any additional comments?
Same family as #5993 / #6463 / #8121. We have already applied all known workarounds and the crash persists:
<transition>around<keep-alive>(avoids the 3.5.x emptyPlaceholder issue).v-forkeys are stable (unique ids per message/segment — not array indexes), so the keyed diff is not being confused by id backfilling.Teleportoverlays use:disabledinstead ofv-ifunmounting;onDeactivatedcloses all floating layers.The crash still occurs 100% of the time in the real app under the sequence above, and the
msgListInDoc=false / domRows=0capture rules out message-key instability: the failing patch targets a detached/null-el subtree during the keep-alive activate move racing with the async re-render scheduled byonActivated.If useful I can attach the full production
electron.logexcerpts (8 occurrences, identical stack) and a stripped-down version of the real component tree.Related: #5993, #6463, #8121, #10517.