Skip to content

fix(db): hydrate disabled live queries without a stream record - #2323

Open
Jaime02 wants to merge 1 commit into
TanStack:mainfrom
Jaime02:fix/disabled-live-query-hydration
Open

Jaime02 wants to merge 1 commit into
TanStack:mainfrom
Jaime02:fix/disabled-live-query-hydration

Conversation

@Jaime02

@Jaime02 Jaime02 commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #2322

🎯 Changes

A live query whose query callback returns undefined has no collection. The server returns the disabled snapshot and never captures or streams a record for its hash. On the browser, LiveQueryObserverClient.getServerSnapshot still waited for that record. The read suspended while the DB stream was open and threw error 253 after the stream ended, so hydration fell back to client rendering.

The fix skips the hydration wait when the observer has no collection (one condition in getServerSnapshot). Every framework adapter goes through this shared binding.

🔬 Oracle Coverage

Violated law: a reader's first hydration view reproduces its server view. A disabled reader rendered disabled on the server and has no record, so it owes no wait.

  • Core owner (packages/db/tests/ssr-stream-record-wait-oracle.test.ts): adds a disabled peer reader, with a portable hash, to every generated history (missing, pending, or local record × arrival, close, error, or cleanup × late attempt, peer-first, undefined cause, restart). getServerSnapshot().status must be disabled while transport is open, after each terminal event, and on a fresh stream after cleanup.
    • RED on unchanged production: the read throws the wait promise while transport is open. With the open-stream checkpoint removed, a close history fails with "The DB stream ended before the server-rendered query snapshot arrived."
    • GREEN with the fix, in both the fixed and random campaigns.
  • Real host (examples/react/start-ssr-e2e): a new /disabled-query route and a case in e2e/ssr-db.spec.ts. They use the real Start serializer, the Router DB stream receiver, hydrateRoot, and Chromium.
    • RED without the fix on both vite preview (production build) and vite dev. The error event's cause is error 253 from _setSsrStreamingEnabled.
    • GREEN with the fix on both.
  • The coverage map entry for the record-wait driver has been updated.

Limits: server/browser disagreement on whether a query is enabled is a separate hydration mismatch and is not covered here.

✅ Checklist

  • I have tested this code locally with pnpm test. I ran the db SSR, observer and DbClient suites, the full react-db suite, react-router-with-db, and the Start e2e spec.

🚀 Release Impact

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

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Disabled live queries now complete browser hydration without waiting for a server record or failing when the database stream ends.
    • Disabled query status is preserved while the transport is open, after terminal events, and on a fresh stream.

A query whose callback returns undefined has no collection, so the server
never captures or streams a record for it. The browser hydration read still
waited on its hash: it suspended while the DB stream was open and threw
error 253 once the stream ended, so React fell back to client rendering.

Skip the hydration wait when the observer has no collection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Oct 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2d11707

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

This PR includes changesets to release 24 packages
Name Type
@tanstack/db Patch
@tanstack/angular-db Patch
@tanstack/capacitor-db-sqlite-persistence-e2e-app Patch
@tanstack/convex-db-collection Patch
@tanstack/db-sqlite-persistence-core Patch
@tanstack/electric-db-collection Patch
@tanstack/expo-db-sqlite-persistence-e2e-app Patch
@tanstack/powersync-db-collection Patch
@tanstack/preact-db Patch
@tanstack/react-db Patch
@tanstack/rxdb-db-collection Patch
@tanstack/solid-db Patch
@tanstack/svelte-db Patch
@tanstack/tauri-db-sqlite-persistence-e2e-app Patch
@tanstack/trailbase-db-collection Patch
@tanstack/vue-db Patch
@tanstack/browser-db-sqlite-persistence Patch
@tanstack/capacitor-db-sqlite-persistence Patch
@tanstack/cloudflare-durable-objects-db-sqlite-persistence Patch
@tanstack/electron-db-sqlite-persistence Patch
@tanstack/expo-db-sqlite-persistence Patch
@tanstack/node-db-sqlite-persistence Patch
@tanstack/react-native-db-sqlite-persistence Patch
@tanstack/tauri-db-sqlite-persistence 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

coderabbitai Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4018ceb9-2c43-4b22-adb5-563b0c46c1f5
Commits

Reviewing files that changed from the base of the PR and between 15d2d2d and 2d11707.

Files selected for processing: 7
  • .changeset/disabled-query-hydration.md
  • docs/contributing/oracle-coverage.md
  • examples/react/start-ssr-e2e/e2e/ssr-db.spec.ts
  • examples/react/start-ssr-e2e/src/routeTree.gen.ts
  • examples/react/start-ssr-e2e/src/routes/disabled-query.tsx
  • packages/db/src/live-query-observer-client.ts
  • packages/db/tests/ssr-stream-record-wait-oracle.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Walkthrough

Browser-side SSR snapshot reads now wait for a server query record only when an observer has a collection. Tests cover disabled status during open, terminal, and fresh-stream states, plus hydration in a React end-to-end route.

Changes: Disabled query hydration

Layer / File(s) Summary
Browser SSR wait and stream-state coverage
packages/db/src/live-query-observer-client.ts, packages/db/tests/ssr-stream-record-wait-oracle.test.ts, docs/contributing/oracle-coverage.md, .changeset/disabled-query-hydration.md
The browser SSR wait now requires a collection. Oracle coverage checks that a disabled observer remains disabled across stream states. The docs and changeset describe the behavior.
React SSR end-to-end coverage
examples/react/start-ssr-e2e/src/routes/disabled-query.tsx, examples/react/start-ssr-e2e/src/routeTree.gen.ts, examples/react/start-ssr-e2e/e2e/ssr-db.spec.ts
The example adds and registers /disabled-query. The end-to-end test checks hydration completion, disabled query status, and browser errors.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related PRs

  • TanStack/db#2168: Introduced the live-query status model and disabled-query result semantics used by this change.
  • TanStack/db#2229: Updated SSR snapshot preparation and subscription demand; this change also modifies the browser SSR snapshot path.

Suggested reviewers: kyleamathews, tannerlinsley

Merge Risk: Minimal · up to 2d117

The disabled-query hydration change is ready to merge with no established blocking risk.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title "fix(db): hydrate disabled live queries without a stream record" matches the main change. The PR makes LiveQueryObserverClient.getServerSnapshot skip the hydration wait when a live query has…
Description check Passed The description follows the repository template. It includes the Changes section with the motivation and the fix (one condition in getServerSnapshot). It includes the Oracle Coverage section, which na…
Linked Issues check Passed Issue [#2322] requires a disabled useLiveQuery to hydrate with status: 'disabled' without waiting for a server record. LiveQueryObserverClient.getServerSnapshot now skips the SSR wait when `this…
Out of Scope Changes check Passed The production guard directly fixes [#2322]. The core oracle, end-to-end route and test, generated route metadata, coverage documentation, and patch changeset support or document that fix. No unrelate…
Full details: Title check

Explanation

The title "fix(db): hydrate disabled live queries without a stream record" matches the main change. The PR makes LiveQueryObserverClient.getServerSnapshot skip the hydration wait when a live query has no collection (its query callback returns undefined), so disabled queries hydrate with status 'disabled' and no server record. The title is specific, uses a conventional prefix, and names the affected package and behavior.

Full details: Description check

Explanation

The description follows the repository template. It includes the Changes section with the motivation and the fix (one condition in getServerSnapshot). It includes the Oracle Coverage section, which names the violated law, the core owner test file, the RED/GREEN results for the unit property test and the Start e2e host, and the remaining limits. It also includes the Checklist with the test run and the Release Impact section with the changeset box checked. The description has a few minor gaps: it does not state the coverage-map owner by its exact name in the template's terms, and the Oracle Coverage section is long for a single condition change. These gaps do not reduce completeness.

Full details: Linked Issues check

Explanation

Issue [#2322] requires a disabled useLiveQuery to hydrate with status: 'disabled' without waiting for a server record. LiveQueryObserverClient.getServerSnapshot now skips the SSR wait when this.collection is absent. The new core oracle checks disabled status while transport is open, after terminal events, and on a fresh stream. The new /disabled-query Playwright test checks hydration, disabled status, and no browser errors.

Full details: Out of Scope Changes check

Explanation

The production guard directly fixes [#2322]. The core oracle, end-to-end route and test, generated route metadata, coverage documentation, and patch changeset support or document that fix. No unrelated change is demonstrated.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 2 functions across 5 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Disabled useLiveQuery fails SSR hydration with error 253

1 participant