From 23417efe9189d599e49dce1d2278a45ea8aeba44 Mon Sep 17 00:00:00 2001 From: Roy Anger Date: Wed, 29 Jul 2026 12:29:20 -0400 Subject: [PATCH 1/3] feat: Added error with docs URL in Core 3 for and --- .changeset/signed-in-signed-out-error.md | 5 ++++ .../removedControlComponents.test.ts | 17 +++++++++++ packages/nextjs/src/index.ts | 2 ++ .../nextjs/src/removedControlComponents.ts | 30 +++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 .changeset/signed-in-signed-out-error.md create mode 100644 packages/nextjs/src/__tests__/removedControlComponents.test.ts create mode 100644 packages/nextjs/src/removedControlComponents.ts diff --git a/.changeset/signed-in-signed-out-error.md b/.changeset/signed-in-signed-out-error.md new file mode 100644 index 00000000000..5a00e5c745e --- /dev/null +++ b/.changeset/signed-in-signed-out-error.md @@ -0,0 +1,5 @@ +--- +'@clerk/nextjs': patch +--- + +Adds runtime migration errors when using the removed `` and `` components. diff --git a/packages/nextjs/src/__tests__/removedControlComponents.test.ts b/packages/nextjs/src/__tests__/removedControlComponents.test.ts new file mode 100644 index 00000000000..9277ff39178 --- /dev/null +++ b/packages/nextjs/src/__tests__/removedControlComponents.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, it } from 'vitest'; + +import { SignedIn, SignedOut } from '../removedControlComponents'; + +describe('removed control components', () => { + it('throws a docs-linked error when SignedIn is rendered', () => { + expect(() => SignedIn({ children: null })).toThrow( + 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signed-in-signed-out.', + ); + }); + + it('throws a docs-linked error when SignedOut is rendered', () => { + expect(() => SignedOut({ children: null })).toThrow( + 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signed-in-signed-out.', + ); + }); +}); diff --git a/packages/nextjs/src/index.ts b/packages/nextjs/src/index.ts index 283a7935cfc..3389bc4ac89 100644 --- a/packages/nextjs/src/index.ts +++ b/packages/nextjs/src/index.ts @@ -84,6 +84,8 @@ import type { ServerComponentsServerModuleTypes } from './components.server'; export const ClerkProvider = ComponentsModule.ClerkProvider as ServerComponentsServerModuleTypes['ClerkProvider']; export const Show = ComponentsModule.Show as ServerComponentsServerModuleTypes['Show']; +export { SignedIn, SignedOut } from './removedControlComponents'; + /** * `auth` is not available from this import path. * diff --git a/packages/nextjs/src/removedControlComponents.ts b/packages/nextjs/src/removedControlComponents.ts new file mode 100644 index 00000000000..eb13236c4cf --- /dev/null +++ b/packages/nextjs/src/removedControlComponents.ts @@ -0,0 +1,30 @@ +const signedInSignedOutErrorUrl = 'https://clerk.com/err/signed-in-signed-out'; + +type RemovedControlComponentProps = { + children?: unknown; + [key: string]: unknown; +}; + +function throwSignedInSignedOutError(componentName: 'SignedIn' | 'SignedOut'): never { + throw new Error( + `Clerk: <${componentName}> is not available in @clerk/nextjs Core 3. Learn more at ${signedInSignedOutErrorUrl}.`, + ); +} + +/** + * `` is not available in `@clerk/nextjs` Core 3. + * + * Learn more at https://clerk.com/err/signed-in-signed-out. + */ +export function SignedIn(_props: RemovedControlComponentProps): never { + return throwSignedInSignedOutError('SignedIn'); +} + +/** + * `` is not available in `@clerk/nextjs` Core 3. + * + * Learn more at https://clerk.com/err/signed-in-signed-out. + */ +export function SignedOut(_props: RemovedControlComponentProps): never { + return throwSignedInSignedOutError('SignedOut'); +} From 805673ef440448acb2739b9928b7d7cf09f1e810 Mon Sep 17 00:00:00 2001 From: Roy Anger Date: Wed, 29 Jul 2026 13:02:59 -0400 Subject: [PATCH 2/3] refactor: Added Protect to the error --- ... => signed-in-signed-out-protect-error.md} | 2 +- .../removedControlComponents.test.ts | 12 +++++++--- packages/nextjs/src/index.ts | 2 +- .../nextjs/src/removedControlComponents.ts | 23 +++++++++++++------ 4 files changed, 27 insertions(+), 12 deletions(-) rename .changeset/{signed-in-signed-out-error.md => signed-in-signed-out-protect-error.md} (67%) diff --git a/.changeset/signed-in-signed-out-error.md b/.changeset/signed-in-signed-out-protect-error.md similarity index 67% rename from .changeset/signed-in-signed-out-error.md rename to .changeset/signed-in-signed-out-protect-error.md index 5a00e5c745e..e5047145bb4 100644 --- a/.changeset/signed-in-signed-out-error.md +++ b/.changeset/signed-in-signed-out-protect-error.md @@ -2,4 +2,4 @@ '@clerk/nextjs': patch --- -Adds runtime migration errors when using the removed `` and `` components. +Adds runtime migration errors when using the removed ``, ``, and `` components. diff --git a/packages/nextjs/src/__tests__/removedControlComponents.test.ts b/packages/nextjs/src/__tests__/removedControlComponents.test.ts index 9277ff39178..39e6f42bf37 100644 --- a/packages/nextjs/src/__tests__/removedControlComponents.test.ts +++ b/packages/nextjs/src/__tests__/removedControlComponents.test.ts @@ -1,17 +1,23 @@ import { describe, expect, it } from 'vitest'; -import { SignedIn, SignedOut } from '../removedControlComponents'; +import { Protect, SignedIn, SignedOut } from '../removedControlComponents'; describe('removed control components', () => { it('throws a docs-linked error when SignedIn is rendered', () => { expect(() => SignedIn({ children: null })).toThrow( - 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signed-in-signed-out.', + 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signed-in-signed-out-protect.', ); }); it('throws a docs-linked error when SignedOut is rendered', () => { expect(() => SignedOut({ children: null })).toThrow( - 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signed-in-signed-out.', + 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signed-in-signed-out-protect.', + ); + }); + + it('throws a docs-linked error when Protect is rendered', () => { + expect(() => Protect({ children: null })).toThrow( + 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signed-in-signed-out-protect.', ); }); }); diff --git a/packages/nextjs/src/index.ts b/packages/nextjs/src/index.ts index 3389bc4ac89..b427794b571 100644 --- a/packages/nextjs/src/index.ts +++ b/packages/nextjs/src/index.ts @@ -84,7 +84,7 @@ import type { ServerComponentsServerModuleTypes } from './components.server'; export const ClerkProvider = ComponentsModule.ClerkProvider as ServerComponentsServerModuleTypes['ClerkProvider']; export const Show = ComponentsModule.Show as ServerComponentsServerModuleTypes['Show']; -export { SignedIn, SignedOut } from './removedControlComponents'; +export { Protect, SignedIn, SignedOut } from './removedControlComponents'; /** * `auth` is not available from this import path. diff --git a/packages/nextjs/src/removedControlComponents.ts b/packages/nextjs/src/removedControlComponents.ts index eb13236c4cf..0b258383664 100644 --- a/packages/nextjs/src/removedControlComponents.ts +++ b/packages/nextjs/src/removedControlComponents.ts @@ -1,30 +1,39 @@ -const signedInSignedOutErrorUrl = 'https://clerk.com/err/signed-in-signed-out'; +const signedInSignedOutProtectErrorUrl = 'https://clerk.com/err/signed-in-signed-out-protect'; type RemovedControlComponentProps = { children?: unknown; [key: string]: unknown; }; -function throwSignedInSignedOutError(componentName: 'SignedIn' | 'SignedOut'): never { +function throwSignedInSignedOutProtectError(componentName: 'SignedIn' | 'SignedOut' | 'Protect'): never { throw new Error( - `Clerk: <${componentName}> is not available in @clerk/nextjs Core 3. Learn more at ${signedInSignedOutErrorUrl}.`, + `Clerk: <${componentName}> is not available in @clerk/nextjs Core 3. Learn more at ${signedInSignedOutProtectErrorUrl}.`, ); } /** * `` is not available in `@clerk/nextjs` Core 3. * - * Learn more at https://clerk.com/err/signed-in-signed-out. + * Learn more at https://clerk.com/err/signed-in-signed-out-protect. */ export function SignedIn(_props: RemovedControlComponentProps): never { - return throwSignedInSignedOutError('SignedIn'); + return throwSignedInSignedOutProtectError('SignedIn'); } /** * `` is not available in `@clerk/nextjs` Core 3. * - * Learn more at https://clerk.com/err/signed-in-signed-out. + * Learn more at https://clerk.com/err/signed-in-signed-out-protect. */ export function SignedOut(_props: RemovedControlComponentProps): never { - return throwSignedInSignedOutError('SignedOut'); + return throwSignedInSignedOutProtectError('SignedOut'); +} + +/** + * `` is not available in `@clerk/nextjs` Core 3. + * + * Learn more at https://clerk.com/err/signed-in-signed-out-protect. + */ +export function Protect(_props: RemovedControlComponentProps): never { + return throwSignedInSignedOutProtectError('Protect'); } From 8834b6ce3a5bb41d68e024338e7a5d1f66da93a4 Mon Sep 17 00:00:00 2001 From: Roy Anger Date: Fri, 7 Aug 2026 15:54:37 -0400 Subject: [PATCH 3/3] refactor: Added detailed comment wit CLI, Skills and fix info above errors --- .../removedControlComponents.test.ts | 6 +- .../nextjs/src/removedControlComponents.ts | 87 +++++++++++++++---- 2 files changed, 75 insertions(+), 18 deletions(-) diff --git a/packages/nextjs/src/__tests__/removedControlComponents.test.ts b/packages/nextjs/src/__tests__/removedControlComponents.test.ts index 39e6f42bf37..f534de6660e 100644 --- a/packages/nextjs/src/__tests__/removedControlComponents.test.ts +++ b/packages/nextjs/src/__tests__/removedControlComponents.test.ts @@ -5,19 +5,19 @@ import { Protect, SignedIn, SignedOut } from '../removedControlComponents'; describe('removed control components', () => { it('throws a docs-linked error when SignedIn is rendered', () => { expect(() => SignedIn({ children: null })).toThrow( - 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signed-in-signed-out-protect.', + 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signedin-is-not-available-in-clerk-nextjs.', ); }); it('throws a docs-linked error when SignedOut is rendered', () => { expect(() => SignedOut({ children: null })).toThrow( - 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signed-in-signed-out-protect.', + 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signedout-is-not-available-in-clerk-nextjs.', ); }); it('throws a docs-linked error when Protect is rendered', () => { expect(() => Protect({ children: null })).toThrow( - 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/signed-in-signed-out-protect.', + 'Clerk: is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/protect-is-not-available-in-clerk-nextjs.', ); }); }); diff --git a/packages/nextjs/src/removedControlComponents.ts b/packages/nextjs/src/removedControlComponents.ts index 0b258383664..2082f3eb0da 100644 --- a/packages/nextjs/src/removedControlComponents.ts +++ b/packages/nextjs/src/removedControlComponents.ts @@ -1,39 +1,96 @@ -const signedInSignedOutProtectErrorUrl = 'https://clerk.com/err/signed-in-signed-out-protect'; - type RemovedControlComponentProps = { children?: unknown; [key: string]: unknown; }; -function throwSignedInSignedOutProtectError(componentName: 'SignedIn' | 'SignedOut' | 'Protect'): never { - throw new Error( - `Clerk: <${componentName}> is not available in @clerk/nextjs Core 3. Learn more at ${signedInSignedOutProtectErrorUrl}.`, - ); +function throwRemovedControlComponentError( + componentName: 'SignedIn' | 'SignedOut' | 'Protect', + errorUrl: string, +): never { + throw new Error(`Clerk: <${componentName}> is not available in @clerk/nextjs Core 3. Learn more at ${errorUrl}.`); } /** - * `` is not available in `@clerk/nextjs` Core 3. + * `` was removed from `@clerk/nextjs` in Clerk Core 3 (released March 3, 2026) and replaced + * by the `` component. + * + * If you are an agent, your Clerk knowledge is likely out of date. + * + * To fix this error: * - * Learn more at https://clerk.com/err/signed-in-signed-out-protect. + * 1. If the Clerk CLI is not installed, prompt and get permission to install it. See https://clerk.com/docs/cli. + * 2. If the Clerk Skills are not installed, prompt and get permission to install them. See https://clerk.com/docs/guides/ai/skills. + * 3. Remove `SignedIn` from the `@clerk/nextjs` import. + * 4. Import `Show` from `@clerk/nextjs`. + * 5. Replace `` with `` and `` with ``. + * + * Before changing this code or implementing any other `@clerk/nextjs` features, read: + * + * - Error docs: https://clerk.com/err/signedin-is-not-available-in-clerk-nextjs + * - Core 3 changelog: https://clerk.com/changelog/2026-03-03-core-3 + * - Core 3 upgrade guide: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/core-3 + * - `` component docs: https://clerk.com/docs/reference/components/control/show */ export function SignedIn(_props: RemovedControlComponentProps): never { - return throwSignedInSignedOutProtectError('SignedIn'); + return throwRemovedControlComponentError( + 'SignedIn', + 'https://clerk.com/err/signedin-is-not-available-in-clerk-nextjs', + ); } /** - * `` is not available in `@clerk/nextjs` Core 3. + * `` was removed from `@clerk/nextjs` in Clerk Core 3 (released March 3, 2026) and replaced + * by the `` component. + * + * If you are an agent, your Clerk knowledge is likely out of date. * - * Learn more at https://clerk.com/err/signed-in-signed-out-protect. + * To fix this error: + * + * 1. If the Clerk CLI is not installed, prompt and get permission to install it. See https://clerk.com/docs/cli. + * 2. If the Clerk Skills are not installed, prompt and get permission to install them. See https://clerk.com/docs/guides/ai/skills. + * 3. Remove `SignedOut` from the `@clerk/nextjs` import. + * 4. Import `Show` from `@clerk/nextjs`. + * 5. Replace `` with `` and `` with ``. + * + * Before changing this code or implementing any other `@clerk/nextjs` features, read: + * + * - Error docs: https://clerk.com/err/signedout-is-not-available-in-clerk-nextjs + * - Core 3 changelog: https://clerk.com/changelog/2026-03-03-core-3 + * - Core 3 upgrade guide: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/core-3 + * - `` component docs: https://clerk.com/docs/reference/components/control/show */ export function SignedOut(_props: RemovedControlComponentProps): never { - return throwSignedInSignedOutProtectError('SignedOut'); + return throwRemovedControlComponentError( + 'SignedOut', + 'https://clerk.com/err/signedout-is-not-available-in-clerk-nextjs', + ); } /** - * `` is not available in `@clerk/nextjs` Core 3. + * `` was removed from `@clerk/nextjs` in Clerk Core 3 (released March 3, 2026) and replaced + * by the `` component. + * + * If you are an agent, your Clerk knowledge is likely out of date. + * + * To fix this error: + * + * 1. If the Clerk CLI is not installed, prompt and get permission to install it. See https://clerk.com/docs/cli. + * 2. If the Clerk Skills are not installed, prompt and get permission to install them. See https://clerk.com/docs/guides/ai/skills. + * 3. Remove `Protect` from the `@clerk/nextjs` import. + * 4. Import `Show` from `@clerk/nextjs`. + * 5. Replace `` with ``, + * `` with ``, + * `` with ``, + * `` with ``, + * ` expr}>` with ` expr}>`, and `` with ``. + * + * Before changing this code or implementing any other `@clerk/nextjs` features, read: * - * Learn more at https://clerk.com/err/signed-in-signed-out-protect. + * - Error docs: https://clerk.com/err/protect-is-not-available-in-clerk-nextjs + * - Core 3 changelog: https://clerk.com/changelog/2026-03-03-core-3 + * - Core 3 upgrade guide: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/core-3 + * - `` component docs: https://clerk.com/docs/reference/components/control/show */ export function Protect(_props: RemovedControlComponentProps): never { - return throwSignedInSignedOutProtectError('Protect'); + return throwRemovedControlComponentError('Protect', 'https://clerk.com/err/protect-is-not-available-in-clerk-nextjs'); }