Skip to content

Solid 2: presence read on async derived store stays blank after resolution #3726

Description

@GabbeV

Describe the bug

An in expression on a derived createStore stays blank after its pending source resolves. A sibling expression reading the source signal updates to resolved, but the presence expression neither shows present nor missing.

The component returns a pending promise from the store derivation, then sets the source signal to [1] and resolves that promise with [1] in the same timer callback. The read is inside <Loading>, which has finished showing its fallback.

Your Example Website or App

https://s.olid.uk/id/ffhim7PpQ5G0sPHlyO7JPg

Steps to Reproduce the Bug or Issue

  1. Open the playground and click Build.
  2. Wait for Source: resolved.
  3. Observe that Presence: has no value.

Expected behavior

Presence: present. The derived store has resolved to [1], and length exists on that array.

Platform

  • OS: Linux
  • Browser: Chromium 153.0.8010.12
  • Solid: 2.0.0-rc.13

Activity

  1. GabbeV commented on Sep 30, 2026

    @GabbeV
    Author

    A more application-shaped repro: https://s.olid.uk/id/MrvPyNcpS1GI7r0LqJ8FEw

    1. Click Build. The To do lane initially contains “Review the proposal,” and the count reads All cards: 1.
    2. Click Activity, then Board.
    3. The count still reads All cards: 1, but the lane is empty.

    The board view uses an async card source, a derived createStore, createOptimisticStore, and a keyed <For>. The count lives outside the view that is remounted. This shows the user-visible failure in a board-like setting; I have not established that it shares the same root cause as the direct presence-read repro above.

  2. added a commit that references this issue on Oct 5, 2026
  3. ryansolid commented on Oct 5, 2026

    @ryansolid
    Member

    Fixed on next by #3789 (a036c226c) — thanks for the reproduction and the board playground.

    The shape is pinned under L2, including the issue's setTimeout sequence, the held-landing variant, and the board shape from this thread (it was the held-landing variant; it passes).

    Mechanism: on L2 a derive with a flight up is read tracked through pullFamily, so the parked reader is linked to the firewall node and re-runs in the landing's flush; under a hold it re-runs as the transaction's work and reveals at land.

    Closing manually — auto-close did not fire because next is not the default branch.

    — Claude via Cursor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions