Skip to content

+page mounts twice on one navigation when a persistent layout renders an outgoing route's teleported snippet #16166

Description

@torrfura

Describe the bug

With compilerOptions.experimental.async: true, a destination route's +page is instantiated twice on a single client-side navigation — its onMount runs twice, and the first instance is created, rendered, then torn down again while still reactively alive (which surfaces as derived_inert warnings in a real app). With the flag off, it mounts once.

There are no await expressions in the reproduction, so this is not about async data or update coordination — only the experimental.async rendering machinery's mount/teardown.

Three conditions are required together (removing any one → single mount):

  1. A persistent layout renders a snippet teleported up from a descendant — the descendant registers a snippet via a context store, and the persistent layout renders it elsewhere in its own tree (a portal); the layout survives the navigation.
  2. The outgoing route teleports its own child route ({@render children()}) through that persistent layout.
  3. The destination is a 2-level route (+layout + +page).

Only the destination +page leaf doubles; its +layout and the persistent host mount once. It is specifically the persistent host rendering the outgoing route's teleported snippet, concurrent with the navigation — deleting just that {@render slot.teleported()} (keeping everything else) makes it mount once, and rendering a host-owned snippet in the same spot does not trigger it.

Reproduction

https://github.com/torrfura/sveltekit-async-double-mount

npm install && npm run dev   # http://localhost:5173

Open the console, click /teleporter, then click /nested. The single /teleporter → /nested navigation mounts nested/+page twice. The on-page panel resets per navigation and shows a verdict, so there's nothing cumulative to misread.

Controls (each removes one condition → single mount):

Navigation Outgoing teleports its child? Destination dest +page mounts
/teleporter → /nested yes 2-level twice
/teleporter → /flat yes 1-level once
/inline → /nested no 2-level once

Logs

### Logs


🐛 DOUBLE MOUNT: nested/+page mounted 2× in one navigation → /nested

System Info

System:
  OS: macOS 26.5.1
Binaries:
  Node: 24.14.0
  npm: 11.9.0
npmPackages:
  svelte: 5.56.3
  @sveltejs/kit: 3.0.0-next.4
  @sveltejs/vite-plugin-svelte: 7.1.2
  vite: 8.0.16

Severity

annoyance

Additional Information

This stems from ideas like these: #627 But in our case it's about layout orchestration and animation using view transitions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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