Skip to content

router@2.0.0-next.20 hangs indefinitely on a lazy route reading a query() gated behind another one #595

Description

@davedbase

Summary

Client-side navigation into a lazy()-loaded route hangs forever — the <Loading> fallback never resolves — when the route reads a query()-backed value that is itself gated behind a separate, already-pending query()-backed value:

const orgId = createMemo(() => profile()?.orgId);
const record = createMemo(() => {
  const oid = orgId();
  return oid ? getRecord(oid) : undefined;
});

This is a very common pattern — "wait for the session/org to resolve before fetching anything that depends on it." It works correctly on 2.0.0-next.19 and regresses starting at 2.0.0-next.20 (also broken on next.21, latest as of this report).

Reproduction

Minimal repo: <link to your pushed solid-router-repro repo here>

  1. pnpm install
  2. pnpm dev
  3. Open the app, click through to the lazy /detail/:id route (client-side nav, not a full page load).
  4. The "Loading record…" fallback never resolves — confirmed stuck after 12+ seconds, not just slow. DevTools shows only the dev-mode ASYNC_OUTSIDE_LOADING_BOUNDARY / STRICT_READ_UNTRACKED warnings, no thrown error.
  5. Change @solidjs/router to 2.0.0-next.19 in package.json, reinstall, repeat the same click: resolves normally.

What was ruled out

  • Not a UI or userland issue — reproduces with solid-js + @solidjs/router only, no UI library involved.
  • Not a solid-js/@solidjs/web version issuerc.3 and rc.5 both work fine when the router is held at next.19.
  • Not about the number of concurrent queries — reproduces with a single gated query, and also with nine spread across multiple panels.
  • Not a query()-specific artifact of memos in general — a raw createMemo(() => somePromise) instead of query() does not hang, on any router version tested. query() specifically is required.
  • Not triggered by independent queries — independent (non-gated) query() calls, i.e. no dependency between them, do not hang. The gating (one query() value depending on another, still-pending query() value) is required to trigger it.

Suspected cause

dist/routing.js changed substantially between next.19 and next.20: the client-side lazy-route-resolution path was rewritten from

throw new NotReadyError(Promise.all(pending.map(resolveLazySubtree)))

to a per-boundary readLazySubtree() that wraps resolveLazySubtree() in runWithOwner(routerOwner, () => createMemo(...)).

That new per-router-owner memo-based reader looks like the prime suspect — the hang only appears on a lazy()-loaded route, and only when a dependent query() chain is involved.

Your Example Website or App

https://stackblitz.com/edit/github-y2k9kdyh-1eadwkhr

Steps to Reproduce the Bug or Issue

  1. Visit reproduction link
  2. Click on link
  3. Observe the route hangs indefinitely

Expected behavior

Route should resolve and load correctly.

Screenshots or Videos

No response

Platform

  • solid-js / @solidjs/web: 2.0.0-rc.5
  • @solidjs/router: 2.0.0-next.20 (repros) / 2.0.0-next.19 (works)
  • Vite 8.2.2, @solidjs/vite-plugin 3.0.0-next.37
  • Reproduced in headless Chromium (Playwright) and confirmed with a 12s+ wait
    (not a slow-resolve, genuinely stuck)

Additional context

No response

Activity

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