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
Optimistic writes disappear on rows retained from a derived store's draft #3859
After the refresh, an action optimistically sets the retained row's value to 1 and waits two seconds. The optimistic view keeps showing 0 throughout the action.
There are no concurrent actions or pending source updates; the setup updates finish before the action starts.
Click Run once. The button creates a local row, refreshes the source, then starts the optimistic action, with 100 ms delays between setup updates.
Observe that Local value stays at 0 during the two-second action.
Expected behavior
The optimistic view should show Local value: 1 while the action is pending, then revert to 0 when the action finishes without persisting the change.
Screenshots or Videos
No response
Platform
OS: Linux
Browser: Chromium 153.0.8010.12
Solid: published preview mizulu/solid2@5c2174c
Additional context
Returning a copy of the retained row (draft.filter(...).map(row => ({ ...row }))) makes the optimistic update appear and revert as expected. Both variants were tested in the browser.
The retained-draft-row pattern is already covered for ordinary writes by the regression tests for #3767. This report concerns optimistic writes over that store.
Confirmed, and thanks for the minimal pattern. It reproduces on next and with #3855 (which fixes a different case). It needs the re-derivation: without the source refresh, the retained row shows the guess and reverts correctly, and copying the row avoids it, as you found. So the optimistic view most likely still tracks the row from before the refresh. It needs its own fix; we'll pin your repro as a test.
Fixed in #3876 (merged into next as d1309ad). Thanks @GabbeV for the minimal repro and the copy workaround; the workaround pointed straight at the cause.
A correction to our earlier comment: the optimistic view did track the right row. Its proxy and targets are the same objects before and after the refresh. What changes is the derived store's committed array. Your derive returns the draft wrapper from draft.filter(...), and since the #3767 fix that wrapper is registered as an alias of the row, so it sits in the committed array in place of the row's raw object. Reads through the derived store resolve the alias, which is why everything looked fine.
The optimistic setter's draft clones that committed array. The wrapper forwards $TARGET, so the chained read took it for a store proxy and skipped resolving it. It then wrapped it as a second row target, and the write became a guess on nodes nothing read. A copied row is a plain object, so it resolved to the real row target, which is why your workaround worked.
The fix resolves anything that isn't a real store proxy on that path. Your sequence is now a regression test, along with the copied-row variant as a control.
Activity
ryansolid commentedon Oct 7, 2026
fix(signals): resolve a retained derived-store draft row under an opt…
ryansolid commentedon Oct 7, 2026