Skip to content

fix(solid-query): strip promise field in hydratableObserverResult to …#10104

Open
erikrahm wants to merge 2 commits intoTanStack:mainfrom
erikrahm:patch-1
Open

fix(solid-query): strip promise field in hydratableObserverResult to …#10104
erikrahm wants to merge 2 commits intoTanStack:mainfrom
erikrahm:patch-1

Conversation

@erikrahm
Copy link

@erikrahm erikrahm commented Feb 8, 2026

🎯 Changes

hydratableObserverResult() strips refetch, fetchNextPage, and fetchPreviousPage during SSR, but doesn't strip the promise field from QueryObserverResult.

The promise field (from QueryObserver.getOptimisticResult()) is a controlled Promise that may never resolve — for example when enabled: false. When included in the value returned from createResource's fetcher, Solid's SSR serialization waits for it indefinitely, causing the streaming response to never close (browser tab spinner spins forever).

Fix: Add promise: undefined alongside the existing refetch: undefined.

Reproduction

  1. Create a Solid component that uses useQuery with enabled: false:
import { useQuery } from '@tanstack/solid-query'                                                    

const App = () => {
  const query = useQuery(() => ({
    queryKey: ['test'],
    queryFn: () => Promise.resolve('hello'),
    enabled: false,
  }))
  return <div>{query.status}</div>
}
  1. Render with Solid's streaming SSR (renderToStream)
  2. The SSR response stream never closes, document.readyState stays 'loading' and the browser tab
    spinner spins forever

Any query that doesn't immediately fetch is affected, not just enabled: false. This includes queries where the server sets enabled: !isServer as a global default.

✅ Checklist

  • I have followed the steps in the Contributing
    guide
    .
  • I have tested this code locally with pnpm run test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a
    changeset.
  • This change is docs/CI/dev-only (no release).

…prevent SSR stream hang

The promise field from QueryObserver.getOptimisticResult() is a controlled Promise that may never resolve (e.g. when enabled: false). When included in the value returned from createResource's fetcher, Solid's SSR serialization waits for it indefinitely, causing the streaming response to never close.
                                                                                                      
This follows the same pattern as the existing refetch: undefined stripping.
@changeset-bot
Copy link

changeset-bot bot commented Feb 8, 2026

🦋 Changeset detected

Latest commit: 6b3f382

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@tanstack/solid-query Patch
@tanstack/solid-query-devtools Patch
@tanstack/solid-query-persist-client Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

📝 Walkthrough

Walkthrough

Adds a changeset documenting a patch fix for @tanstack/solid-query that prevents SSR stream hangs by explicitly removing non-serializable promise fields during hydration. The useBaseQuery.ts file is updated to set promise and refetch to undefined when handling SSR-hydrated results.

Changes

Cohort / File(s) Summary
Release Metadata
.changeset/curly-places-train.md
Adds changeset file documenting patch fix for SSR promise field serialization issue.
SSR Hydration Logic
packages/solid-query/src/useBaseQuery.ts
Explicitly removes non-serializable values (promise, refetch) during SSR hydration to prevent stream hangs; updates accompanying comment to clarify removal and reconstruction of non-serializable fields.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested labels

package: solid-query

Suggested reviewers

  • TkDodo

Poem

🐰 A promise once hung in the SSR stream,
But now it's undefined—a hydration dream!
No more serialized fields causing woe,
Just clean extraction, ready to go! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: stripping the promise field in hydratableObserverResult during SSR, which directly corresponds to the primary fix in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The pull request description comprehensively covers the problem, solution, reproduction steps, and release impact with all required sections completed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant