Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

@clerk/nextjs: onBeforeSetActive never settles when invalidateCacheAction rejects (e.g. after a redeploy), so setActive and signOut hang forever

Open Beginner friendly
#9,987 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@RaphaelFakhri is already working on this.

Since Oct 6, 2026.

  • #10088 by @RaphaelFakhri — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
next.js, react

Research direction

Start in dist/esm/app-router/client/ClerkProvider.js at window.__internal_onBeforeSetActive and inspect how invalidateCacheAction() handles rejection. Reproduce with the provided stale-tab redeploy steps, then verify the hook settles and sign-in, sign-out, and reverification complete after the cache-invalidation action fails.

Written by the indexing model from the issue text.

Description

Preliminary Checks
  • I have reviewed the documentation: https://clerk.com/docs
  • I have searched for existing issues: https://github.com/clerk/javascript/issues
  • I have not already reached out to Clerk support via email or Discord
  • This issue is not a question, general help request, or anything other than a bug report directly related to Clerk.
Reproduction

No public repo: the steps below reproduce it in any App Router app using @clerk/nextjs, and the faulty code path is two lines, quoted below.

Publishable key

pk_test_YnJpZWYtc2N1bHBpbi00NS5jbGVyay5hY2NvdW50cy5kZXYk (a development instance; the bug does not depend on the instance, and we hit it in production first)

Description

The App Router client ClerkProvider sets (@clerk/nextjs 7.4.1, dist/esm/app-router/client/ClerkProvider.js; the same code is in 7.9.7):

window.__internal_onBeforeSetActive = (intent) => {
  return new Promise((resolve) => {
    const nextVersion = window?.next?.version || "";
    if ((nextVersion.startsWith("15") || nextVersion.startsWith("16")) && intent === "sign-out") {
      resolve();
    } else {
      void invalidateCacheAction().then(() => resolve());
    }
  });
};

If invalidateCacheAction() rejects, resolve is never called and the promise never settles. clerk-js awaits this hook inside setActive and signOut, so they hang forever.

The rejection is routine on any self-hosted Next 15/16 app. Server action IDs are salted with a per-build encryption key, so after every redeploy a tab loaded from the previous build calls an action ID the new server does not know. The server answers 404 with x-nextjs-action-not-found: 1 and logs Failed to find Server Action "…". This request might be from an older or newer deployment., and Next rejects the call with UnrecognizedActionError. A network failure has the same effect.

What we measured, in tabs opened before a deploy:

  • Sign-in and reverification (a password change in <UserProfile />) spin forever.
  • signOut() calls the hook with no intent, so the Next 15/16 "sign-out" fast path does not apply, and it awaits the hook before removeSessions(). A stale-tab sign-out therefore leaves the user signed in.

Steps to reproduce:

  1. A fresh create-next-app (App Router) with @clerk/nextjs and a <UserButton /> on a page.
  2. NEXT_SERVER_ACTIONS_ENCRYPTION_KEY=$(openssl rand -base64 32) next build && next start, open the page and sign in.
  3. Stop the server and rebuild with a different NEXT_SERVER_ACTIONS_ENCRYPTION_KEY (two plain local builds reuse the key cached in .next/cache/.rscinfo and keep the same IDs), then next start again. Do not reload the tab.
  4. In that tab, sign out from the <UserButton />, or run await window.__internal_onBeforeSetActive() in the console.

Expected behavior:

The hook settles even when the cache-invalidation action fails (__internal_onAfterSetActive already calls router.refresh()), and sign-out, sign-in and reverification complete.

Actual behavior:

The promise never settles, the UI spins, and on sign-out the session is not removed. The console shows Uncaught (in promise) UnrecognizedActionError: Server Action "…" was not found on the server.

Suggested fix: invalidateCacheAction().then(() => resolve(), () => resolve()), or skip the action on Next ≥ 15 as #7873 proposed. Related prior art: #5084 and #7873 (closed unmerged), and #8122 (a never-settling variant with cacheComponents).

Our app-side workaround re-points window.__internal_onBeforeSetActive, from a descendant useEffect, to a wrapper that races Clerk's promise against an unhandledrejection listener for UnrecognizedActionError and a timeout.

Environment
next: 16.2.6 (webpack build, output: standalone, self-hosted)
@clerk/nextjs: 7.4.1 (the hook is identical in 7.9.7)
@clerk/clerk-js: 6.x (loaded from the CDN by major version)
react / react-dom: 19.2.4
node: 22 (production image)
browser: Chrome
Dominant language
TypeScript
Stars
1.8k
Forks
477
Avg merge
1d 18h
Merged PRs (30d)
287

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from clerk/javascript

All issues in clerk/javascript

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.