Hacktoberfest 2026: as issues que os mantenedores marcaram para outubro, abertas e boas para iniciantes. Ver issues do Hacktoberfest

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

Aberta Para iniciantes
#9,987 1 comentário 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

@RaphaelFakhri já está trabalhando nisso.

Desde 6/10/2026.

  • #10088 de @RaphaelFakhri — aberto

Avaliação

Dificuldade
2/5
Tempo estimado
1-3 horas
Facilidade para iniciantes
78/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
next.js, react

Direção de pesquisa

Comece em dist/esm/app-router/client/ClerkProvider.js, em window.__internal_onBeforeSetActive, e inspecione como invalidateCacheAction() trata uma rejeição. Reproduza usando as etapas fornecidas de redeploy com uma aba obsoleta e, em seguida, verifique se o hook chega a um estado final e se o login, o logout e a reverificação são concluídos depois que a ação de invalidação do cache falhar.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

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
Linguagem predominante
TypeScript
Estrelas
1.8k
Forks
480
Merge médio
1d 19h
PRs com merge (30d)
285

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de clerk/javascript

Todas as issues de clerk/javascript

Issues semelhantes

Mais issues de TypeScript

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.