Repository navigation
clerk-js ignores new ClerkProvider options after the first load, so afterSignOutUrl keeps its first value #10538
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 (if you have, no need to open an issue here)
-
This issue is not a question, general help request, or anything other than a bug report directly related to Clerk. Please ask questions in our Discord community: https://clerk.com/discord.
Reproduction
https://github.com/Joozty/clerk-nextjs-activity-repro
Publishable key
Not shared. The reproduction works with any development instance: put your own key in .env.local (see .env.example).
Description
clerk-js keeps the options from its first load(). If a prop of <ClerkProvider> changes later, clerk-js ignores the new value. For example, an app with two languages passes afterSignOutUrl="/en" or afterSignOutUrl="/sk". A user opens /en, clicks a link to /sk, and signs out. Clerk sends the user to /en, not to /sk.
This happens with or without cacheComponents. #5935 had the same cause for signInUrl. Its author closed it without a fix, and it is now locked.
Steps to reproduce:
- Clone the reproduction and run
pnpm install. - Copy
.env.exampleto.env.local. Set the publishable key of your own development instance there. - Run
pnpm devand open http://localhost:3000/en. - Click the
/sklink. The layout now renders<ClerkProvider afterSignOutUrl="/sk">. - Click Read Clerk.buildAfterSignOutUrl().
Expected behavior:
http://localhost:3000/sk.
Actual behavior:
http://localhost:3000/en. <UserButton> signs out to the URL from clerk.buildAfterSignOutUrl() (see packages/ui/src/contexts/components/UserButton.ts). I tested this with a real account: after I click /sk and sign out, I land on /en.
Why it happens:
- When you click
/sk, the newClerkProvidersends its options to clerk-js. Its effect calls__internal_updateProps({ options }), and the options includeafterSignOutUrl: "/sk". I checked this in the browser. Clerk.__internal_updateProps()inpackages/clerk-js/src/core/clerk.tsmerges the new options withthis.#options. But it gives the result only to Clerk's UI. It never saves it inthis.#options. Onlyload()setsthis.#options.buildAfterSignOutUrl(),buildSignInUrl(),buildSignUpUrl(),buildAfterSignInUrl()andbuildAfterSignUpUrl()readthis.#options. So they keep the first values.- There is a second, smaller problem in
@clerk/react. The effect inpackages/react/src/contexts/ClerkProvider.tsxthat calls__internal_updateProps({ options })depends only on[mergedOptions.localization]. So if oneClerkProviderstays mounted and onlyafterSignOutUrlchanges, the new value is not even sent.
#4498 added the merge in __internal_updateProps. Its changeset says "Re-init window.Clerk options when ClerkProvider props change", but the code only gives the merged options to the UI.
Possible fix:
- In
__internal_updateProps, save the merged options inthis.#options. This alone should fix the reproduction. - In
@clerk/react, send the options again when any option changes, not onlylocalization. This is for apps where oneClerkProviderstays mounted.
Workaround: custom code can call signOut({ redirectUrl }). But <UserButton> has no prop for the sign-out URL. By default, clerk-js loads from the Frontend API, not from node_modules, so a pnpm patch in the app can't fix it.
Related:
- Localizations #372 added the
@clerk/reacteffect that sends options only whenlocalizationchanges. - fix(clerk-js): Update props while respecting defaults set by Clerk.load #3455 also merged the options of a new
ClerkProvideronly into the UI state. - feat: remove deprecated props #7243 removed
<UserButton afterSignOutUrl>in Core 3, so<UserButton>has no prop for the sign-out URL.
Environment
System:
OS: macOS 27.2
CPU: (10) arm64 Apple M4
Memory: 73.23 MB / 32.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.15.0 - /Users/jozef/.volta/tools/image/node/24.15.0/bin/node
npm: 11.12.1 - /Users/jozef/.volta/tools/image/node/24.15.0/bin/npm
pnpm: 12.4.1 - /Users/jozef/.volta/bin/pnpm
Browsers:
Chrome: 156.0.8078.48
Firefox: 159.0
Safari: 27.2
npmPackages:
@clerk/nextjs: 7.9.22 => 7.9.22
next: 16.4.3 => 16.4.3
react: 19.3.0 => 19.3.0
react-dom: 19.3.0 => 19.3.0
Loaded from the Frontend API:
@clerk/clerk-js: 6.41.0 (6.42.0 and main have the same code)
@clerk/ui: 1.42.0
Activity