Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/signed-in-signed-out-protect-error.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/nextjs': patch
---

Adds runtime migration errors when using the removed `<SignedIn>`, `<SignedOut>`, and `<Protect>` components.
23 changes: 23 additions & 0 deletions packages/nextjs/src/__tests__/removedControlComponents.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { describe, expect, it } from 'vitest';

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: <SignedIn> 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: <SignedOut> 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: <Protect> is not available in @clerk/nextjs Core 3. Learn more at https://clerk.com/err/protect-is-not-available-in-clerk-nextjs.',
);
});
});
2 changes: 2 additions & 0 deletions packages/nextjs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ import type { ServerComponentsServerModuleTypes } from './components.server';
export const ClerkProvider = ComponentsModule.ClerkProvider as ServerComponentsServerModuleTypes['ClerkProvider'];
export const Show = ComponentsModule.Show as ServerComponentsServerModuleTypes['Show'];

export { Protect, SignedIn, SignedOut } from './removedControlComponents';

/**
* `auth` is not available from this import path.
*
Expand Down
96 changes: 96 additions & 0 deletions packages/nextjs/src/removedControlComponents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
type RemovedControlComponentProps = {
children?: unknown;
[key: string]: unknown;
};

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}.`);
}

/**
* `<SignedIn>` was removed from `@clerk/nextjs` in Clerk Core 3 (released March 3, 2026) and replaced
* by the `<Show>` 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 `SignedIn` from the `@clerk/nextjs` import.
* 4. Import `Show` from `@clerk/nextjs`.
* 5. Replace `<SignedIn>` with `<Show when="signed-in">` and `</SignedIn>` with `</Show>`.
*
* 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
* - `<Show>` component docs: https://clerk.com/docs/reference/components/control/show
*/
export function SignedIn(_props: RemovedControlComponentProps): never {
return throwRemovedControlComponentError(
'SignedIn',
'https://clerk.com/err/signedin-is-not-available-in-clerk-nextjs',
);
}

/**
* `<SignedOut>` was removed from `@clerk/nextjs` in Clerk Core 3 (released March 3, 2026) and replaced
* by the `<Show>` 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 `SignedOut` from the `@clerk/nextjs` import.
* 4. Import `Show` from `@clerk/nextjs`.
* 5. Replace `<SignedOut>` with `<Show when="signed-out">` and `</SignedOut>` with `</Show>`.
*
* 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
* - `<Show>` component docs: https://clerk.com/docs/reference/components/control/show
*/
export function SignedOut(_props: RemovedControlComponentProps): never {
return throwRemovedControlComponentError(
'SignedOut',
'https://clerk.com/err/signedout-is-not-available-in-clerk-nextjs',
);
}

/**
* `<Protect>` was removed from `@clerk/nextjs` in Clerk Core 3 (released March 3, 2026) and replaced
* by the `<Show>` 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 `<Protect role="admin">` with `<Show when={{ role: 'admin' }}>`,
* `<Protect permission="org:billing:manage">` with `<Show when={{ permission: 'org:billing:manage' }}>`,
* `<Protect feature="widgets">` with `<Show when={{ feature: 'widgets' }}>`,
* `<Protect plan="pro">` with `<Show when={{ plan: 'pro' }}>`,
* `<Protect condition={(has) => expr}>` with `<Show when={(has) => expr}>`, and `</Protect>` with `</Show>`.
*
* Before changing this code or implementing any other `@clerk/nextjs` features, read:
*
* - 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
* - `<Show>` component docs: https://clerk.com/docs/reference/components/control/show
*/
export function Protect(_props: RemovedControlComponentProps): never {
return throwRemovedControlComponentError('Protect', 'https://clerk.com/err/protect-is-not-available-in-clerk-nextjs');
}
Loading