sveltejs / svelte · Issue No. 18489
A $derived declared as a class field is "owned" by whatever effect happens to be active when the instance is constructed (derived.parent = active_effect). If that instance outlives the effect, e.g. a long-lived model object that was new'd inside a component which later unmounts, the derived is frozen to its last value and never recomputes again, even though its $state dependencies keep changing.
This is a regression introduced in 5.55.3 by #17921; pinning to 5.55.2 restores correct behavior.
The trap is that the owning effect is non-deterministic and semantically meaningless for an object whose lifetime isn't tied to any component, it's just whichever effect was on the stack at new-time.
https://svelte.dev/playground/86e9f769bb1d4021af59f2d289b73448?version=5.56.4
Click the button twice.
Expected: after step 2, box.value === 'C' so box.doubled === 'CC'.
Actual (5.55.3+): box.doubled === 'BB', frozen at the value from before the child unmounted. Reading it inside a reactive context (template/$effect) instead reconnects and unfreezes it, which makes the staleness order-dependent and hard to spot.
System:
OS: macOS 26.4.1
CPU: (14) arm64 Apple M4 Pro
Memory: 3.37 GB / 48.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.18.0 - /Users/reinhard/.nvm/versions/node/v22.18.0/bin/node
npm: 10.9.4 - /Users/reinhard/.nvm/versions/node/v22.18.0/bin/npm
bun: 1.3.14 - /Users/reinhard/.bun/bin/bun
Browsers:
Brave Browser: 146.1.88.134
Chrome: 149.0.7827.156
Firefox: 152.0.3
Safari: 26.4
npmPackages:
rollup: ^4.56.0 => 4.56.0
blocking an upgrade
Relay reads this issue against the repository's contribution signals: the files it is likely to touch, how the maintainers triage work this size, and what the first contribution would exercise.
The full analysis for this issue is still being assembled. Until then, the description above and the thread on GitHub are the most reliable context.