From 20a4d8ebc4ffa6874cb8f14989e60dae6818e1c9 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Wed, 4 Nov 2026 14:17:24 -0800 Subject: [PATCH 1/6] fix(react-router): remove the ignored rootAuthLoader options --- .../root-auth-loader-options-removed.md | 5 +++ .../server/__tests__/rootAuthLoader.test.ts | 6 ++++ .../react-router/src/server/rootAuthLoader.ts | 14 ++++----- packages/react-router/src/server/types.ts | 31 ++++--------------- packages/react-router/src/types/index.ts | 1 - 5 files changed, 23 insertions(+), 34 deletions(-) create mode 100644 .changeset/root-auth-loader-options-removed.md diff --git a/.changeset/root-auth-loader-options-removed.md b/.changeset/root-auth-loader-options-removed.md new file mode 100644 index 00000000000..ef2020d41c9 --- /dev/null +++ b/.changeset/root-auth-loader-options-removed.md @@ -0,0 +1,5 @@ +--- +'@clerk/react-router': patch +--- + +Remove the unused `options` argument from the `rootAuthLoader()` types. `rootAuthLoader` reads auth state from `clerkMiddleware()` and has ignored these options since v3, so values like `secretKey`, `signInUrl`, or `loadUser` passed to it had no effect. TypeScript now reports these calls, so you can move the options to `clerkMiddleware()`. The `RootAuthLoaderOptions` type is removed, and `request.user`, `request.session`, and `request.organization` are no longer typed on the callback request, because their runtime value was always `undefined`. Existing calls that still pass options keep working at runtime. diff --git a/packages/react-router/src/server/__tests__/rootAuthLoader.test.ts b/packages/react-router/src/server/__tests__/rootAuthLoader.test.ts index a1da41dae47..4108e2fdd87 100644 --- a/packages/react-router/src/server/__tests__/rootAuthLoader.test.ts +++ b/packages/react-router/src/server/__tests__/rootAuthLoader.test.ts @@ -50,6 +50,12 @@ describe('rootAuthLoader', () => { await rootAuthLoader(args, () => ({ data: 'test' })); }); + it('should ignore a non-function second argument from older call sites', async () => { + const result = await rootAuthLoader(args, { secretKey: 'sk_test_ignored' } as any); + + expect(result).toHaveProperty('clerkState'); + }); + it('should handle no callback', async () => { const result = await rootAuthLoader(args); diff --git a/packages/react-router/src/server/rootAuthLoader.ts b/packages/react-router/src/server/rootAuthLoader.ts index 5a1d625e604..b828888ff9f 100644 --- a/packages/react-router/src/server/rootAuthLoader.ts +++ b/packages/react-router/src/server/rootAuthLoader.ts @@ -8,7 +8,6 @@ import type { LoaderFunctionArgsWithAuth, LoaderFunctionReturn, RootAuthLoaderCallback, - RootAuthLoaderOptions, } from './types'; import { getResponseClerkState, @@ -20,7 +19,7 @@ import { } from './utils'; interface RootAuthLoader { - >( + ( /** * Arguments passed to the loader function. */ @@ -29,10 +28,9 @@ interface RootAuthLoader { * A loader function with authentication state made available to it. Allows you to fetch route data based on the user's authentication state. */ callback: Callback, - options?: Options, ): Promise>; - (args: LoaderFunctionArgs, options?: RootAuthLoaderOptions): Promise; + (args: LoaderFunctionArgs): Promise; } /** @@ -42,7 +40,7 @@ async function processRootAuthLoader( args: LoaderFunctionArgs, requestState: RequestState, additionalState: AdditionalStateOptions, - handler?: RootAuthLoaderCallback, + handler?: RootAuthLoaderCallback, ): Promise { const hasMiddleware = IsOptIntoMiddleware(args.context) && !!args.context.get(authFnContext); const includeClerkHeaders = !hasMiddleware; @@ -59,7 +57,7 @@ async function processRootAuthLoader( const argsWithAuth = { ...args, request: Object.assign(args.request, { auth: requestState.toAuth() }), - } as LoaderFunctionArgsWithAuth; + } as LoaderFunctionArgsWithAuth; const handlerResult = await handler(argsWithAuth); @@ -115,9 +113,9 @@ async function processRootAuthLoader( */ export const rootAuthLoader: RootAuthLoader = async ( args: LoaderFunctionArgs, - handlerOrOptions: any, + callback?: unknown, ): Promise => { - const handler = typeof handlerOrOptions === 'function' ? handlerOrOptions : undefined; + const handler = typeof callback === 'function' ? (callback as RootAuthLoaderCallback) : undefined; const hasMiddlewareFlag = IsOptIntoMiddleware(args.context); const contextValue = hasMiddlewareFlag && args.context.get(requestStateContext); diff --git a/packages/react-router/src/server/types.ts b/packages/react-router/src/server/types.ts index 9342f6b39af..d0e83cf9116 100644 --- a/packages/react-router/src/server/types.ts +++ b/packages/react-router/src/server/types.ts @@ -1,4 +1,4 @@ -import type { Organization, Session, User, VerifyTokenOptions } from '@clerk/backend'; +import type { VerifyTokenOptions } from '@clerk/backend'; import type { OrganizationSyncOptions, RequestState, @@ -48,21 +48,6 @@ export type ClerkMiddlewareOptions = { SignUpForceRedirectUrl & SignUpFallbackRedirectUrl; -export type RootAuthLoaderOptions = ClerkMiddlewareOptions & { - /** - * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead. - */ - loadUser?: boolean; - /** - * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead. - */ - loadSession?: boolean; - /** - * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead. - */ - loadOrganization?: boolean; -}; - export interface KeylessUrls { __keylessClaimUrl?: string; __keylessApiKeysUrl?: string; @@ -84,9 +69,7 @@ export type RequestStateWithRedirectUrls = RequestState & SignUpFallbackRedirectUrl & KeylessUrls; -export type RootAuthLoaderCallback = ( - args: LoaderFunctionArgsWithAuth, -) => RootAuthLoaderCallbackReturn; +export type RootAuthLoaderCallback = (args: LoaderFunctionArgsWithAuth) => RootAuthLoaderCallbackReturn; type ObjectLike = Record | null; @@ -105,12 +88,10 @@ type RootAuthLoaderCallbackReturn = export type LoaderFunctionReturn = ReturnType; -export type LoaderFunctionArgsWithAuth = LoaderFunctionArgs & { - request: RequestWithAuth; +export type LoaderFunctionArgsWithAuth = LoaderFunctionArgs & { + request: RequestWithAuth; }; -export type RequestWithAuth = LoaderFunctionArgs['request'] & { +export type RequestWithAuth = LoaderFunctionArgs['request'] & { auth: Omit; -} & (Options extends { loadSession: true } ? { session: Session | null } : object) & - (Options extends { loadUser: true } ? { user: User | null } : object) & - (Options extends { loadOrganization: true } ? { organization: Organization | null } : object); +}; diff --git a/packages/react-router/src/types/index.ts b/packages/react-router/src/types/index.ts index 7522c192d1f..600251f7f60 100644 --- a/packages/react-router/src/types/index.ts +++ b/packages/react-router/src/types/index.ts @@ -19,5 +19,4 @@ export type { RequestStateWithRedirectUrls, RequestWithAuth, RootAuthLoaderCallback, - RootAuthLoaderOptions, } from '../server/types'; From e6f3318ba01d80429796bf49356a3887200fa784 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Wed, 4 Nov 2026 14:20:43 -0800 Subject: [PATCH 2/6] chore(react-router): release the rootAuthLoader options removal as a minor --- .changeset/root-auth-loader-options-removed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/root-auth-loader-options-removed.md b/.changeset/root-auth-loader-options-removed.md index ef2020d41c9..36f9294e515 100644 --- a/.changeset/root-auth-loader-options-removed.md +++ b/.changeset/root-auth-loader-options-removed.md @@ -1,5 +1,5 @@ --- -'@clerk/react-router': patch +'@clerk/react-router': minor --- Remove the unused `options` argument from the `rootAuthLoader()` types. `rootAuthLoader` reads auth state from `clerkMiddleware()` and has ignored these options since v3, so values like `secretKey`, `signInUrl`, or `loadUser` passed to it had no effect. TypeScript now reports these calls, so you can move the options to `clerkMiddleware()`. The `RootAuthLoaderOptions` type is removed, and `request.user`, `request.session`, and `request.organization` are no longer typed on the callback request, because their runtime value was always `undefined`. Existing calls that still pass options keep working at runtime. From 91c49485a2a8035d240ba3aab69a38e339e1e80b Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Wed, 4 Nov 2026 14:21:06 -0800 Subject: [PATCH 3/6] chore(react-router): simplify the rootAuthLoader changeset --- .changeset/root-auth-loader-options-removed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/root-auth-loader-options-removed.md b/.changeset/root-auth-loader-options-removed.md index 36f9294e515..a9978732c91 100644 --- a/.changeset/root-auth-loader-options-removed.md +++ b/.changeset/root-auth-loader-options-removed.md @@ -2,4 +2,4 @@ '@clerk/react-router': minor --- -Remove the unused `options` argument from the `rootAuthLoader()` types. `rootAuthLoader` reads auth state from `clerkMiddleware()` and has ignored these options since v3, so values like `secretKey`, `signInUrl`, or `loadUser` passed to it had no effect. TypeScript now reports these calls, so you can move the options to `clerkMiddleware()`. The `RootAuthLoaderOptions` type is removed, and `request.user`, `request.session`, and `request.organization` are no longer typed on the callback request, because their runtime value was always `undefined`. Existing calls that still pass options keep working at runtime. +Remove the `options` argument from `rootAuthLoader()`. It had no effect, since `rootAuthLoader` reads auth state from `clerkMiddleware()`. Pass options like `secretKey` or `signInUrl` to `clerkMiddleware()` instead. The `RootAuthLoaderOptions` type is also removed. From 29f408039a5ab26e60b3b067ecf6feacad3bfac6 Mon Sep 17 00:00:00 2001 From: Robert Soriano Date: Wed, 4 Nov 2026 14:21:58 -0800 Subject: [PATCH 4/6] Update root-auth-loader-options-removed.md --- .changeset/root-auth-loader-options-removed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/root-auth-loader-options-removed.md b/.changeset/root-auth-loader-options-removed.md index a9978732c91..b4ac9062a32 100644 --- a/.changeset/root-auth-loader-options-removed.md +++ b/.changeset/root-auth-loader-options-removed.md @@ -2,4 +2,4 @@ '@clerk/react-router': minor --- -Remove the `options` argument from `rootAuthLoader()`. It had no effect, since `rootAuthLoader` reads auth state from `clerkMiddleware()`. Pass options like `secretKey` or `signInUrl` to `clerkMiddleware()` instead. The `RootAuthLoaderOptions` type is also removed. +Remove the leftover `options` argument from `rootAuthLoader()`. It had no effect, since `rootAuthLoader` reads auth state from `clerkMiddleware()`. Pass options like `secretKey` or `signInUrl` to `clerkMiddleware()` instead. The `RootAuthLoaderOptions` type is also removed. From 0b941df506ba034f541b1d32b79ae7986524437c Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Wed, 4 Nov 2026 14:37:37 -0800 Subject: [PATCH 5/6] fix(react-router): keep RootAuthLoaderOptions and the callback generics for compatibility --- .../root-auth-loader-options-removed.md | 2 +- packages/react-router/src/server/types.ts | 28 ++++++++++++++++--- packages/react-router/src/types/index.ts | 1 + 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/.changeset/root-auth-loader-options-removed.md b/.changeset/root-auth-loader-options-removed.md index b4ac9062a32..491f9ea0b3e 100644 --- a/.changeset/root-auth-loader-options-removed.md +++ b/.changeset/root-auth-loader-options-removed.md @@ -2,4 +2,4 @@ '@clerk/react-router': minor --- -Remove the leftover `options` argument from `rootAuthLoader()`. It had no effect, since `rootAuthLoader` reads auth state from `clerkMiddleware()`. Pass options like `secretKey` or `signInUrl` to `clerkMiddleware()` instead. The `RootAuthLoaderOptions` type is also removed. +Remove the `options` argument from `rootAuthLoader()`. It had no effect, since `rootAuthLoader` reads auth state from `clerkMiddleware()`. Pass options like `secretKey` or `signInUrl` to `clerkMiddleware()` instead. The `rootAuthLoader()` callback request no longer types `request.user`, `request.session`, or `request.organization`, because they were always `undefined`. `RootAuthLoaderOptions` is deprecated in favor of `ClerkMiddlewareOptions`. diff --git a/packages/react-router/src/server/types.ts b/packages/react-router/src/server/types.ts index d0e83cf9116..fbeb42db861 100644 --- a/packages/react-router/src/server/types.ts +++ b/packages/react-router/src/server/types.ts @@ -48,6 +48,24 @@ export type ClerkMiddlewareOptions = { SignUpForceRedirectUrl & SignUpFallbackRedirectUrl; +/** + * @deprecated Use `ClerkMiddlewareOptions` instead. `rootAuthLoader()` no longer accepts options. + */ +export type RootAuthLoaderOptions = ClerkMiddlewareOptions & { + /** + * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead. + */ + loadUser?: boolean; + /** + * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead. + */ + loadSession?: boolean; + /** + * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead. + */ + loadOrganization?: boolean; +}; + export interface KeylessUrls { __keylessClaimUrl?: string; __keylessApiKeysUrl?: string; @@ -69,7 +87,9 @@ export type RequestStateWithRedirectUrls = RequestState & SignUpFallbackRedirectUrl & KeylessUrls; -export type RootAuthLoaderCallback = (args: LoaderFunctionArgsWithAuth) => RootAuthLoaderCallbackReturn; +export type RootAuthLoaderCallback = ( + args: LoaderFunctionArgsWithAuth, +) => RootAuthLoaderCallbackReturn; type ObjectLike = Record | null; @@ -88,10 +108,10 @@ type RootAuthLoaderCallbackReturn = export type LoaderFunctionReturn = ReturnType; -export type LoaderFunctionArgsWithAuth = LoaderFunctionArgs & { - request: RequestWithAuth; +export type LoaderFunctionArgsWithAuth = LoaderFunctionArgs & { + request: RequestWithAuth; }; -export type RequestWithAuth = LoaderFunctionArgs['request'] & { +export type RequestWithAuth<_Options extends RootAuthLoaderOptions = any> = LoaderFunctionArgs['request'] & { auth: Omit; }; diff --git a/packages/react-router/src/types/index.ts b/packages/react-router/src/types/index.ts index 600251f7f60..7522c192d1f 100644 --- a/packages/react-router/src/types/index.ts +++ b/packages/react-router/src/types/index.ts @@ -19,4 +19,5 @@ export type { RequestStateWithRedirectUrls, RequestWithAuth, RootAuthLoaderCallback, + RootAuthLoaderOptions, } from '../server/types'; From 9967ba7a8d7f135a639c79ac53ddca578efdb19c Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Wed, 4 Nov 2026 14:45:30 -0800 Subject: [PATCH 6/6] fix(react-router): alias RootAuthLoaderOptions to ClerkMiddlewareOptions --- .changeset/root-auth-loader-options-removed.md | 2 +- packages/react-router/src/server/types.ts | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/.changeset/root-auth-loader-options-removed.md b/.changeset/root-auth-loader-options-removed.md index 491f9ea0b3e..6955bd34632 100644 --- a/.changeset/root-auth-loader-options-removed.md +++ b/.changeset/root-auth-loader-options-removed.md @@ -2,4 +2,4 @@ '@clerk/react-router': minor --- -Remove the `options` argument from `rootAuthLoader()`. It had no effect, since `rootAuthLoader` reads auth state from `clerkMiddleware()`. Pass options like `secretKey` or `signInUrl` to `clerkMiddleware()` instead. The `rootAuthLoader()` callback request no longer types `request.user`, `request.session`, or `request.organization`, because they were always `undefined`. `RootAuthLoaderOptions` is deprecated in favor of `ClerkMiddlewareOptions`. +Remove the `options` argument from `rootAuthLoader()`. It had no effect, since `rootAuthLoader` reads auth state from `clerkMiddleware()`. Pass options like `secretKey` or `signInUrl` to `clerkMiddleware()` instead. The `rootAuthLoader()` callback request no longer types `request.user`, `request.session`, or `request.organization`, because they were always `undefined`. `RootAuthLoaderOptions` is deprecated in favor of `ClerkMiddlewareOptions`, and its unused `loadUser`, `loadSession`, and `loadOrganization` flags are removed. diff --git a/packages/react-router/src/server/types.ts b/packages/react-router/src/server/types.ts index fbeb42db861..9a627f7a666 100644 --- a/packages/react-router/src/server/types.ts +++ b/packages/react-router/src/server/types.ts @@ -51,20 +51,7 @@ export type ClerkMiddlewareOptions = { /** * @deprecated Use `ClerkMiddlewareOptions` instead. `rootAuthLoader()` no longer accepts options. */ -export type RootAuthLoaderOptions = ClerkMiddlewareOptions & { - /** - * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead. - */ - loadUser?: boolean; - /** - * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead. - */ - loadSession?: boolean; - /** - * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead. - */ - loadOrganization?: boolean; -}; +export type RootAuthLoaderOptions = ClerkMiddlewareOptions; export interface KeylessUrls { __keylessClaimUrl?: string;