Skip to content

solid-query 6.0.0-rc.1: useQuery({ enabled: false }) hangs SSR again (regression of #10907) #11348

Description

@TylerRick

Describe the bug

A useQuery with enabled: false, whose .data is read during render, stops an SSR render from
ever finishing at @tanstack/solid-query 6.0.0-rc.1. Nothing is emitted at all — the render is
stuck before any output, not stalled mid-stream.

This is the same user-visible failure as #10907, which was closed with
"experimental_prefetchInRender has been removed". That did fix the v5 path; the v6 implementation
is different, so I am filing separately rather than commenting there.

Where it comes from in rc.1. In
packages/solid-query/src/useBaseQuery.ts,
computeData() — the derive of the single createProjection that is the data node — ends:

if (state.data !== undefined) return wrap(state.data)

// Pending-idle: nothing in flight, nothing cached. …
if (isEnabled()) {
	
	return chainOnce(q.fetch(opts as any), select, wrap)
}
return NEVER

with
const NEVER: Promise<never> = new Promise(noop).
So a disabled query with no cached data hands the createProjection a promise that can never
settle.

Per its docblock
(L30-L38)
that parking is intentional client behaviour: it suspends the reader into the nearest <Loading>
until the query starts fetching, "at which point the version bump re-runs the compute". On the
server there is no later — the render has to finish, and nothing will enable the query or write
the cache before it does. The three earlier return NEVER guards are each gated
(!isServer && hydrating,
!primed(),
isRestoring())
and observer.setOptions is gated !isServer, but the final disabled
return NEVER
has no isServer branch. rc.0's useBaseQuery carries several if (isServer) special-cases by
contrast.

I have not proposed a patch — what a server read of a disabled query should commit, and where the
guard belongs, looks like your call.

(Permalinks are pinned to the @tanstack/solid-query@6.0.0-rc.1 tag, commit 2222f61f9b71.)

Your minimal, reproducible example

https://github.com/TylerRick/solid-query-disabled-query-ssr-hang-repro

A git repo rather than a sandbox, because the bug only appears in a server render — it is four
files, pnpm install and one node command. Pure Solid SSR: renderToStream, one
QueryClientProvider, one useQuery. No router, no solid-start, no metaframework, no <Loading>
boundary.

import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/solid-query';

const client = new QueryClient();

function Inner() {
	const q = useQuery(() => ({
		queryKey: ['disabled'],
		queryFn: async () => 'data',
		enabled: false,
	}));
	return <div id="out">data: {String(q.data)}</div>;
}

export default function App() {
	return (
		<QueryClientProvider client={client}>
			<Inner />
		</QueryClientProvider>
	);
}

Steps to reproduce

  1. git clone https://github.com/TylerRick/solid-query-disabled-query-ssr-hang-repro && cd solid-query-disabled-query-ssr-hang-repro
  2. pnpm install
  3. ENABLED=0 node render.mjs — renders the component above through @solidjs/web's
    renderToStream and reports whether the stream finishes, with an 8 second cap.
  4. It reports HANG — stream did not finish in 8s (bytes so far: 0).
  5. ENABLED=1 node render.mjs — the identical code with the query enabled — reports
    COMPLETED — 347 bytes.
  6. For the version control, set @tanstack/solid-query to 6.0.0-rc.0 in package.json (leaving
    the @tanstack/query-core override at 5.101.4), pnpm install, and repeat step 3: it
    completes.

Expected behavior

A disabled query has nothing to wait for, so reading .data during SSR should expose the idle
result and allow rendering to finish. rc.0 completes with data: undefined; rc.1 also completes
when the query is enabled.

Instead the render never finishes and no bytes are produced. In a metaframework the effect is that
the page never responds at all.

How often does this bug happen?

Every time

Platform

  • OS: Linux (x64)
  • Node: 24.19.0
  • Browser: n/a — this is a server render

Tanstack Query adapter

solid-query

TanStack Query version

@tanstack/solid-query 6.0.0-rc.1, with @tanstack/query-core 5.101.4 (rc.1's own exact
dependency, pinned in every row below via a direct dependency and a pnpm.overrides entry, so the
query-core bump that normally rides along with rc.1 is held constant).

TypeScript version

n/a for this bug — the reproduction's .tsx is transpiled by vite and never typechecked.

Additional context

The three-cell result, all with query-core held at 5.101.4:

solid-query enabled result
6.0.0-rc.1 false hang — stream never finishes, 0 bytes
6.0.0-rc.1 true completes
6.0.0-rc.0 false completes

Full environment: solid-js / @solidjs/web 2.0.0-rc.4, @solidjs/vite-plugin 3.0.0-next.35
with @solidjs/compiler / @solidjs/babel-plugin 2.0.0-rc.4, vite 8.2.1.

Found upgrading an app to Solid 2.0.0-rc.4, where every page hung: a hook in the root chrome gates
its query with enabled on data only some routes provide, so on every other route that query is
disabled. Through TanStack Start the visible effect is that the SSR-query integration's
queryStream never closes, because router.serverSsr.onRenderFinished(...) is never reached —
but as the reproduction shows, the router is not needed and the defect is not there.

Possibly related, both closed: #10907 (the v5 original) and #8345 (<Suspense> hanging in SSR
with a disabled query).

Two PRs on the v5 line strip the never-resolving promise out of hydratableObserverResult: #10923
(closed unmerged) and #10104 (still open — its description matches this failure mode closely,
including the enabled: false case). Neither approach transfers to v6 as-is: rc.1's useBaseQuery
has no hydratableObserverResult and no createResource, and the equivalent path is the NEVER
returned from computeData into createProjection.

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