Describe the bug
A useQuery with enabled: false never settles its underlying createResource during SSR, so renderToStringAsync (and SolidStart's async/stream SSR) hangs as soon as the disabled query's .data is read during render.
On the server, solid-query forces experimental_prefetchInRender = true (useBaseQuery), so the observer result carries a .promise. For a disabled query that promise never resolves, and the resource fetcher returns it (via hydratableObserverResult) instead of short-circuiting — so the SSR render awaits a promise that can never settle.
Reproduces on @tanstack/solid-query@5.101.0 (latest) with solid-js@1.9.13.
Related, both closed and neither matching this exact symptom (single useQuery, SSR render hang): #6256, #7167.
Your minimal, reproducible example
Standalone Node ESM — no framework needed. solid-js/web resolves to its server build under Node's default node export condition, so isServer === true.
// repro.mjs -> node repro.mjs
import { renderToStringAsync, createComponent, Suspense } from 'solid-js/web'
import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/solid-query'
const client = new QueryClient()
function Inner() {
const q = useQuery(() => ({
queryKey: ['disabled'],
queryFn: () => Promise.resolve('data'), // never runs (disabled)
enabled: false,
}))
return () => `data=${JSON.stringify(q.data)}` // reading data drives the resource
}
const App = () =>
createComponent(QueryClientProvider, {
client,
get children() {
return createComponent(Suspense, {
get children() {
return createComponent(Inner, {})
},
})
},
})
// The race timeout is ONLY so the script exits; renderToStringAsync never settles.
const html = await Promise.race([
renderToStringAsync(() => createComponent(App, {})),
new Promise((_, r) =>
setTimeout(() => r(new Error('renderToStringAsync did not settle (5s)')), 5000),
),
])
console.log(html)
Steps to reproduce
npm i @tanstack/solid-query@5.101.0 solid-js@1.9.13
node repro.mjs
- Observe it never resolves — the 5s race rejects with
renderToStringAsync did not settle.
Expected behavior
A disabled query must not suspend SSR; the resource should resolve immediately with the idle state.
Possible fix
Short-circuiting enabled === false in the useBaseQuery resource fetcher — returning the synchronous result with the dangling .promise stripped — fixes it. Verified locally against 5.101.0:
// inside the createResource fetcher, before `return new Promise(...)`
const obs = observer()
if (obs.options.enabled === false) {
const { promise, ...rest } = hydratableObserverResult(obs.getCurrentQuery(), observerResult)
return rest
}
- unpatched: hangs (5s timeout above)
- with the short-circuit: resolves in ~25ms with the correct idle state
Happy to open a PR if this approach looks right — wanted to confirm the direction first, since it touches the core query path and enabled can also be reactive (this handles the literal false case).
Environment
@tanstack/solid-query@5.101.0, solid-js@1.9.13, Node 24.
Describe the bug
A
useQuerywithenabled: falsenever settles its underlyingcreateResourceduring SSR, sorenderToStringAsync(and SolidStart's async/stream SSR) hangs as soon as the disabled query's.datais read during render.On the server, solid-query forces
experimental_prefetchInRender = true(useBaseQuery), so the observer result carries a.promise. For a disabled query that promise never resolves, and the resource fetcher returns it (viahydratableObserverResult) instead of short-circuiting — so the SSR render awaits a promise that can never settle.Reproduces on
@tanstack/solid-query@5.101.0(latest) withsolid-js@1.9.13.Related, both closed and neither matching this exact symptom (single
useQuery, SSR render hang): #6256, #7167.Your minimal, reproducible example
Standalone Node ESM — no framework needed.
solid-js/webresolves to its server build under Node's defaultnodeexport condition, soisServer === true.Steps to reproduce
npm i @tanstack/solid-query@5.101.0 solid-js@1.9.13node repro.mjsrenderToStringAsync did not settle.Expected behavior
A disabled query must not suspend SSR; the resource should resolve immediately with the idle state.
Possible fix
Short-circuiting
enabled === falsein theuseBaseQueryresource fetcher — returning the synchronous result with the dangling.promisestripped — fixes it. Verified locally against 5.101.0:Happy to open a PR if this approach looks right — wanted to confirm the direction first, since it touches the core query path and
enabledcan also be reactive (this handles the literalfalsecase).Environment
@tanstack/solid-query@5.101.0,solid-js@1.9.13, Node 24.