Skip to content

Streamed Loading boundary duplicates content after Solid Refresh HMR #2919

Description

@brenelz

Describe the bug

With Solid 2 whole-document streamed SSR, a <Loading> boundary can append duplicate resolved content after a Solid Refresh HMR update instead of replacing the previous content.

The page initially renders Hello World2. After reloading once and making repeated text-only edits inside the boundary, the DOM can end up containing output such as:

Hello World2Hello World2333

The duplication only appears after a full page reload followed by HMR. A cold first navigation does not reliably reproduce it, which suggests the cached async client entry allows hydration to begin against the streamed fallback before the server reveal arrives.

This looks related to #2801 bug 1, but that regression coverage exercises a reactive refresh after streamed hydration rather than a component replacement through Solid Refresh HMR.

Your Example Website or App

https://github.com/brenelz/solid-2/tree/b8c94efa

Relevant files:

Versions are pinned in the reproduction:

  • solid-js@2.0.0-beta.20
  • @solidjs/web@2.0.0-beta.20
  • vite-plugin-solid@3.0.0-next.13
  • vite@8.0.10
  • nitro@3.0.260610-beta

Steps to Reproduce the Bug or Issue

  1. Clone the reproduction and check out b8c94efa.
  2. Run pnpm install.
  3. Run pnpm dev.
  4. Open http://localhost:3000 in Chrome and wait for Hello World2 to resolve.
  5. Reload the page once and wait for Hello World2 again.
  6. In src/App.tsx, change the boundary child from {asyncValue()} to {asyncValue()}111 and save.
  7. Wait for the HMR-triggered async operation to settle.
  8. Change 111 to 222, save, and wait for it to settle.
  9. Repeat with 333 if needed.
  10. Observe that resolved values can accumulate instead of replacing the previous DOM.

The artificial one-second delay in the server function makes the boundary transitions visible and deterministic enough to trigger the issue.

Expected behavior

After each HMR update, the boundary should contain exactly one resolved value plus the latest edited text. Previous resolved DOM should be removed rather than retained as a duplicate.

Screenshots or Videos

None yet.

Platform

  • OS: macOS
  • Browser: Chrome
  • Version: unknown

Additional context

  • The SSR output uses renderToStream and passes virtual:solid-manifest.
  • The client hydrates the whole document.
  • The browser entry is emitted as an async module script, matching the vite-plugin-solid SSR example.
  • Server hydration keys and loading-boundary IDs are stable across repeated HTTP requests.
  • A client-only simulation of the installed Solid Refresh runtime replaces the boundary correctly; hydration is required for the duplicate.
  • The issue still occurs on beta.20, which includes the original 2.0.0-beta.15 Many hydration bugs #2801 fixes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions