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
[2.0 / next] A held error replacing a shown error never lands: the screen stays on E1 and E2 escapes as an uncaught error #4410
A memo throws E1, and an Errored boundary shows [E E1]. An action() then writes the source to a value where the memo throws E2 and yields a pending promise, so E2 is held. When the action's promise resolves, the screen should switch to [E E2] (D-41: a held error shows at its landing). Instead the screen stays [E E1], and E2 escapes as an unhandled error from stageError. On next at 81a12d8 the reactive system halts (REACTIVITY_HALTED ... in computed Error: E2). On f94dcd5 and #4406's earlier head it looped in the background until the heap ran out.
It needs three readers besides the boundary:
the boundary's fallback reads the error accessor;
a render effect reads a memo over m;
one more reader: a render effect over m, or a split effect with an error handler.
When m errors, propagateStatus gives the error to its dependents as status, without re-running them. D is marked errored even though its pass would catch the error, and the render effect over D escalates. In the held form the same marking happens when the hold's commit publishes E2, which is why the screen stays on [E E1].
The rules don't say whether a try/catch in a derivation catches an upstream memo's error. Taking it to Ryan before changing it: making the catch work means re-deriving an errored node's dependents instead of marking them.
Maintainer ruling: errors are status. When an upstream memo throws, its readers inherit the error as status without re-running, so a try/catch around m() inside another memo doesn't catch it. Recovery belongs to an Errored boundary. Closing as by design. The docs will state this.
Activity
ryansolid commentedon Oct 29, 2026
Narrowed: the hold, the boundary and the third reader aren't needed. On
next(and as far back as before #4085), this halts on a plain write:When
merrors,propagateStatusgives the error to its dependents as status, without re-running them.Dis marked errored even though its pass would catch the error, and the render effect overDescalates. In the held form the same marking happens when the hold's commit publishes E2, which is why the screen stays on[E E1].The rules don't say whether a
try/catchin a derivation catches an upstream memo's error. Taking it to Ryan before changing it: making the catch work means re-deriving an errored node's dependents instead of marking them.Generated by Claude Code
ryansolid commentedon Oct 29, 2026
Maintainer ruling: errors are status. When an upstream memo throws, its readers inherit the error as status without re-running, so a
try/catcharoundm()inside another memo doesn't catch it. Recovery belongs to anErroredboundary. Closing as by design. The docs will state this.Generated by Claude Code
docs(signals): F-12 — try/catch in a memo does not catch an upstream …
docs(signals): CAUGHT_REACTIVE_READ error arm — errored regardless by…
docs(signals): CAUGHT_REACTIVE_READ error arm — errored regardless by…
test(signals): pin #4486 at the ruled screens — a reader of an errore…
feat(signals): dev diagnostic CAUGHT_REACTIVE_READ — a reactive read'…