From d04d13ea223c1e245bebf05e2ec6af0c27152a53 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Fri, 17 Apr 2026 11:50:49 +1000 Subject: [PATCH] fix: defer child-store root disposal to avoid nested cleanNode disposeDirectory called a createRoot dispose() synchronously. When triggered by pinForOwner's onCleanup during a parent remount (e.g. switching to a WSL server re-keys the ServerKey Show), the inner dispose ran a nested cleanNode cascade on a sibling root while the outer cascade was mid-traversal, corrupting solid-js's graph walk state and surfacing as TypeError: Cannot read properties of null (reading '1') at chunk-*.js:992 after ~155 recursive cleanNode frames. Queue the dispose on a microtask so synchronous bookkeeping still runs (map deletes, onDispose cache invalidation) but the reactive cleanup happens after the outer traversal finishes. --- packages/app/src/context/global-sync/child-store.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/app/src/context/global-sync/child-store.ts b/packages/app/src/context/global-sync/child-store.ts index 3fe67e4fbe..29202110af 100644 --- a/packages/app/src/context/global-sync/child-store.ts +++ b/packages/app/src/context/global-sync/child-store.ts @@ -96,8 +96,15 @@ export function createChildStoreManager(input: { lifecycle.delete(directory) const dispose = disposers.get(directory) if (dispose) { - dispose() disposers.delete(directory) + // Defer the actual solid-js root disposal. When disposeDirectory runs + // from pinForOwner's onCleanup during a parent remount, calling + // dispose() here triggers a nested cleanNode cascade on the inner + // root while the outer cascade is mid-traversal, which corrupts + // solid-js's graph walk state and throws `Cannot read properties of + // null (reading '1')` at chunk-*.js:992. Running dispose on a + // microtask lets the outer cleanup finish first. + queueMicrotask(dispose) } delete children[directory] input.onDispose(directory)