fix(ui): snapshot timeline guard values to stop k(...) is not a function - #1212
fix(ui): snapshot timeline guard values to stop k(...) is not a function#1212EricSanchezok wants to merge 3 commits into
Conversation
TimelineDisplay rendered item branches through non-keyed Switch/Match guards whose memo accessors could be re-evaluated after their responsive owner was disposed during a session switch, throwing k(...) is not a function from Solid's untrack(switchFunc)() guard. Resolve the item once into a discriminated kind snapshot (parseTimelineDisplayItem), key each Match branch on the stable kind string so streaming ticks keep the subtree mounted while kind changes remount, and short-circuit branch children on undefined so a disposed owner degrades to no-match instead of calling a destroyed accessor. Wrap SessionTurn's root render in an ErrorBoundary so residual renderer failures degrade to a localized turn-level error card; the existing TimelineDisplay item boundary stays as the inner defense layer. Covered by session-turn-dispose-guard.dom.test.ts (streaming identity, kind switching, disposed-owner tick) plus the existing boundary/activity DOM tests. Co-authored-by: synergy-agent <299070056+synergy-agent@users.noreply.github.com>
# Conflicts: # packages/ui/src/components/session-turn.tsx
Co-authored-by: synergy-agent <299070056+synergy-agent@users.noreply.github.com>
|
I've completed the review — full static analysis of the Solid runtime semantics plus empirical verification. Here's my report. Review: #1212 — fix(ui): snapshot timeline guard values to stop
|
|
Thanks for the detailed write-up — I read the decision record and the three DOM tests against the solid-js 1.9.10 runtime. Two things need to change before this can land: 1. The turn-level boundary should log + propagate, not degrade to a card Swallowing the error into an error card makes this crash family invisible: The correct behavior is the one the Part boundary (and skill rule 7) already establishes: log with stable IDs only — no message content, tool payloads, or paths — then let the error propagate to the app-level boundary and render solid-js 1.9.10 notes: With log+propagate, 2. The crash still has no verified reproduction The decision record explains the mechanism but has no captured stack, and "the disposed memo accessor returns undefined" is inferred rather than evidenced. In solid 1.9.10 a normally disposed memo keeps its cached value and Please attach the field stack (minified + sourcemapped), or add a case that actually fails on current code — e.g. an update enqueued and the owner disposed before flush, or a live observer reading a destroyed guard accessor. Without a failing case we can't tell whether this PR fixes the reported crash or rearranges the same mechanism. The kind-snapshot core (stable kind key + single parser memo) looks right for keeping streaming remount-free while keying the branches — the concerns are the boundary policy and the missing repro evidence. |
Summary
Eliminates the
k(...) is not a functioncrash class that recurs during session switches, complementing #1211 (session data view layer).parseTimelineDisplayIteminto a discriminated kind snapshot. Each<Match>is keyed on the stable kind string, so streaming ticks (which replace item references via reconcile) keep the subtree mounted — preserving the non-keyed streaming behavior restored in57f8da845— while a genuine kind change (reasoning promotion/collapse, activity mode switch) remounts correctly.undefinedand never re-evaluate a destroyed accessor: a disposed owner degrades to no-match instead of Solid'suntrack(switchFunc)()calling a dead memo and throwingk(...) is not a function.data-slot="session-turn-error", localizedsession-turn.render-error), so previously uncovered guards (shellModePart,specialUserMessageRenderer, theitem()/boundary()Show chain) degrade to a localized turn-level error card. The existing TimelineDisplay item-level boundary stays as the inner defense layer.2026-08-19-timeline-guard-value-snapshot.md) and adds the guard-value invariant to thedevelop-frontendskill.Verification
session-turn-dispose-guard.dom.test.ts(3 cases): streaming identity preserved with content updates, kind flips switch branches without uncaught errors, disposing the owner then ticking surfaces no window error.bun run --cwd packages/ui test542 pass;bun run --cwd packages/app test1581 pass; both packages typecheck;bun run quality:quickall 14 gates pass (incl.decision:check,doc:check,localization:checkwith extracted catalogs).Relation to #1211
#1211 fixes the store-intermediate-state
reading 'find'/'filter'crash class via a null-safe session data view layer. This PR fixes the disposed-owner guard re-evaluation class, which is data-independent and not reachable by the view layer. The two are complementary: together they close the session-switch crash family.