Skip to content

fix(react): Fix stale SSR state during cross-tab sign-out#7865

Open
bratsos wants to merge 2 commits intomainfrom
alexbratsos/user-4721-navigations-can-hang-in-dev-build
Open

fix(react): Fix stale SSR state during cross-tab sign-out#7865
bratsos wants to merge 2 commits intomainfrom
alexbratsos/user-4721-navigations-can-hang-in-dev-build

Conversation

@bratsos
Copy link
Member

@bratsos bratsos commented Feb 17, 2026

Description

When a user signs out in one browser tab, other tabs viewing protected pages hang instead of redirecting to the sign-in page. The page remains stuck showing stale authentication data even though the session has been terminated.

Reproduction:

  • Open two tabs, both authenticated and viewing a protected page
  • Sign out in Tab 2 using UserButton
  • Tab 1 should detect the sign-out and redirect to sign-in
  • Bug: Tab 1 hangs showing stale session data instead of redirecting

Root Cause

The issue was in @clerk/nextjs App Router awaitable navigation:

  • RedirectToSignIn can trigger duplicate router.push calls to the same destination while the first transition is still in flight (commonly observed in dev/StrictMode-like remount/effect replay behavior).
  • The awaitable nav buffer accepted both calls and started another transition for the same URL.
  • In this duplicate in-flight scenario, Next.js may dedupe/cancel the redundant action, leaving isPending stuck and preventing promise buffer flush.

Result: redirect flow appears hung even though auth state is already signed out.

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • Bug Fixes

    • Fix App Router navigation edge case: coalesces duplicate in-flight redirects to the same destination and resets pending navigation state after flush to prevent hangs.
  • Tests

    • Added unit tests covering in-flight navigation deduplication, differing destinations, and post-flush re-navigation.
  • Chores

    • Added a changeset with a patch version bump for the Next.js package.

@vercel
Copy link

vercel bot commented Feb 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Feb 18, 2026 7:46pm

Request Review

@changeset-bot
Copy link

changeset-bot bot commented Feb 17, 2026

🦋 Changeset detected

Latest commit: c683ba9

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

This PR includes changesets to release 1 package
Name Type
@clerk/nextjs 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

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 17, 2026

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@7865

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@7865

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@7865

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@7865

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@7865

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@7865

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@7865

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@7865

@clerk/express

npm i https://pkg.pr.new/@clerk/express@7865

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@7865

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@7865

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@7865

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@7865

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@7865

@clerk/react

npm i https://pkg.pr.new/@clerk/react@7865

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@7865

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@7865

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@7865

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@7865

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@7865

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@7865

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@7865

commit: c683ba9

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

This pull request adds deduplication for App Router navigations in useInternalNavFun, coalescing duplicate in-flight pushes to the same destination by tracking a pendingDestination and reusing a shared promisesBuffer. It introduces a pendingDestination field to Window.__clerk_internal_navigations in global types, updates useInternalNavFun to set/reset the pending state and resolve buffered promises on flush, and adds tests verifying deduplication, non-deduplication for different destinations, and allowing new same-destination pushes after a flush.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title mentions fixing stale SSR state during cross-tab sign-out, but the actual changes focus on fixing duplicate in-flight navigation pushes that could leave awaitable navigation pending, which is the root cause. The title is partially related to the changeset but not the primary technical change. Consider updating the title to better reflect the core fix: deduplication of duplicate same-destination in-flight pushes in awaitable navigation to prevent navigation hangs.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR successfully addresses USER-4721 by fixing the root cause: duplicate in-flight pushes to the same destination that left Clerk's awaitable navigation pending indefinitely, causing cross-tab navigation stalls in dev builds.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the cross-tab navigation hang issue: test file, implementation of deduplication logic, type declarations, and changeset documentation are all aligned with the linked issue objectives.

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


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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.changeset/dry-mangos-fail.md (1)

5-5: Consider adding cross-tab scenario context.

The description is clear and technically accurate. For enhanced user understanding, you could optionally mention the specific cross-tab scenario (e.g., "when signing out in one browser tab while other tabs remain open").

📝 Optional enhancement for user clarity
-Fix navigation hang on cross-tab sign-out by preventing stale SSR state from being used after sign-out detection.
+Fix navigation hang when signing out in one browser tab while other authenticated tabs remain open, by preventing stale SSR state from being used after sign-out detection.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.changeset/dry-mangos-fail.md at line 5, Update the changeset description
"Fix navigation hang on cross-tab sign-out by preventing stale SSR state from
being used after sign-out detection." to explicitly mention the cross-tab
scenario (for example: "when signing out in one browser tab while other tabs
remain open") so users immediately understand the context; keep the technical
explanation about preventing stale SSR state after sign-out detection (the
existing phrase) and append a short example clause referencing the cross-tab
sign-out behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.changeset/dry-mangos-fail.md:
- Line 5: Update the changeset description "Fix navigation hang on cross-tab
sign-out by preventing stale SSR state from being used after sign-out
detection." to explicitly mention the cross-tab scenario (for example: "when
signing out in one browser tab while other tabs remain open") so users
immediately understand the context; keep the technical explanation about
preventing stale SSR state after sign-out detection (the existing phrase) and
append a short example clause referencing the cross-tab sign-out behavior.

Copy link
Member

@jacekradko jacekradko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bratsos I am wondering if other hooks like useUserBase for example have the same issue of returning stale initialState ?

@bratsos bratsos force-pushed the alexbratsos/user-4721-navigations-can-hang-in-dev-build branch from f861ecc to d81e40f Compare February 18, 2026 19:34
@bratsos
Copy link
Member Author

bratsos commented Feb 18, 2026

@bratsos I am wondering if other hooks like useUserBase for example have the same issue of returning stale initialState ?

I completely changed the directory, this was indeed not the issue. Please check again! 🙏

@bratsos bratsos requested a review from Ephem February 18, 2026 19:38
Co-authored-by: Dylan Staley <88163+dstaley@users.noreply.github.com>
Copy link
Member

@Ephem Ephem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a pragmatic fix, nice find! 🙏

'@clerk/nextjs': patch
---

Fix an App Router navigation edge case where duplicate in-flight redirects to the same destination could leave Clerk's awaitable navigation pending indefinitely. We now coalesce duplicate same-destination pushes into a single in-flight transition and reset pending destination state after flush.
Copy link
Member

@Ephem Ephem Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT & subjective: Are the details of how we fixed it necessary here?

Suggested change
Fix an App Router navigation edge case where duplicate in-flight redirects to the same destination could leave Clerk's awaitable navigation pending indefinitely. We now coalesce duplicate same-destination pushes into a single in-flight transition and reset pending destination state after flush.
Fix an App Router navigation edge case where duplicate in-flight redirects to the same destination could leave Clerk's awaitable navigation pending indefinitely.

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.

4 participants

Comments