Skip to content

fix(router-ssr-query-core): drop the query stream reader instead of releasing it - #8796

Open
EmilEinarsen wants to merge 1 commit into
TanStack:mainfrom
EmilEinarsen:fix/ssr-query-webkit-release-lock
Open

EmilEinarsen wants to merge 1 commit into
TanStack:mainfrom
EmilEinarsen:fix/ssr-query-webkit-release-lock

Conversation

@EmilEinarsen

@EmilEinarsen EmilEinarsen commented Oct 23, 2026 •

Copy link
Copy Markdown

🎯 Changes

Fixes #8795.

Hydration no longer calls reader.releaseLock() when the dehydrated query stream ends. In WebKit, releaseLock() can deadlock with a garbage collection and freeze the page right after load. Details and a repro are in the issue.

The loop only exits once the stream is done or the reader has been cancelled. Nothing else reads the stream after that, so the reader is dropped instead of released.

Tests: the three stream.locked === false assertions are gone. The hydration test now asserts releaseLock() is not called, and fails against the old code.

I have seen the freeze only in Playwright's WebKit on Linux. I don't know whether Safari is affected.

Drafted with AI assistance.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with the relevant test commands, or tests do not apply to this pull request.
  • I fully understand the code in this pull request, including any code generated with AI assistance.

Ran on Windows for this package only: unit tests (vitest), eslint, and tsc / tsc6 type checks. I did not run the full pnpm test:eslint / test:types / test:unit across affected packages; a full install fails on Windows (an e2e postinstall uses POSIX env syntax).

🚀 Release Impact

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

Summary by CodeRabbit

  • Bug Fixes
    • Improved reliability when hydrating streamed data in WebKit. Pages are less likely to freeze after a stream finishes or encounters an error.
    • Stream cleanup no longer explicitly releases the reader lock. Hydration continues to cancel streams on failure, while avoiding cleanup behavior that could cause WebKit to stall.

…eleasing it

WebKit's releaseLock() can deadlock with a garbage collection and
freeze the page after hydration.

Fixes TanStack#8795
@changeset-bot

changeset-bot Bot commented Oct 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 055ce1c

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

This PR includes changesets to release 4 packages
Name Type
@tanstack/router-ssr-query-core Patch
@tanstack/react-router-ssr-query Patch
@tanstack/solid-router-ssr-query Patch
@tanstack/vue-router-ssr-query 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 23, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between 6b9fe6d and 055ce1c.

📒 Files selected for processing: 3
  • .changeset/webkit-reader-release-lock.md
  • packages/router-ssr-query-core/src/index.ts
  • packages/router-ssr-query-core/tests/index.test.ts

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

📝 Walkthrough

The hydration stream reader is no longer explicitly released after reading. Tests verify that releaseLock() is not called, and a patch changeset records the change.

Changes: Hydration reader lock handling

Layer / File(s) Summary
Update reader lifecycle and hydration checks
packages/router-ssr-query-core/src/index.ts, packages/router-ssr-query-core/tests/index.test.ts, .changeset/webkit-reader-release-lock.md
The read loop no longer calls releaseLock(). Hydration tests check that it is not called, retain the cancellation assertion, and wait for the expected error in the failed-stream test. A patch changeset records the change.

Priority: ➖ Normal

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

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: schiller-manuel

Merge Risk: ⚪ Minimal · up to 055ce

The change is ready to merge after normal checks; no actionable risk remains identified.

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. Analyzed 1 functions across 2 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description check Passed The description explains the WebKit deadlock issue, the implementation change, test updates, validation performed, test limitations, AI assistance, and release impact. All required template sections a…
Title check Passed The title clearly and concisely describes the primary change: dropping the query stream reader instead of calling releaseLock().
Linked Issues check Passed The PR meets the coding requirements in issue #8795. In packages/router-ssr-query-core/src/index.ts, hydration no longer calls reader.releaseLock() after the query stream read loop. The existing e…
Out of Scope Changes check Passed The changes stay within issue #8795. The source change removes the WebKit deadlock trigger. The test changes verify the new reader lifecycle and preserve failure-path behavior. The changeset supports …
Full details: Description check

Explanation

The description explains the WebKit deadlock issue, the implementation change, test updates, validation performed, test limitations, AI assistance, and release impact. All required template sections are present and substantially complete.

Full details: Linked Issues check

Explanation

The PR meets the coding requirements in issue #8795. In packages/router-ssr-query-core/src/index.ts, hydration no longer calls reader.releaseLock() after the query stream read loop. The existing error path still calls reader.cancel(error). The tests verify that successful hydration does not call releaseLock(), and they retain coverage for stream errors and cancellation. The changeset documents the published behavior change.

Full details: Out of Scope Changes check

Explanation

The changes stay within issue #8795. The source change removes the WebKit deadlock trigger. The test changes verify the new reader lifecycle and preserve failure-path behavior. The changeset supports the published fix. No unrelated implementation or test changes appear in the reviewed diff.

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. Analyzed 1 functions across 2 files. (1 skipped: 1 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

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

This branch has not been deployed

No deployments
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.

router-ssr-query-core: reader.releaseLock() can deadlock WebKit's GC after hydration

1 participant