From f592ba5eb1fb1a827314b2a93a20078b80e5eaea Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Wed, 6 May 2026 10:49:54 -0400 Subject: [PATCH 1/3] fix(nextjs): add runtime error for auth() misimport from main entry point When developers import `auth` from `@clerk/nextjs` instead of `@clerk/nextjs/server`, the bundler shows a generic "'auth' is not exported" error with no guidance. Replace the type-only `declare const` stub with a real runtime Proxy export that throws a clear error message pointing to the correct import path. Ref: SDK-65 Co-Authored-By: Claude Opus 4.6 --- .../src/__tests__/auth-misimport.test.ts | 19 +++++++++++++++++++ packages/nextjs/src/index.ts | 2 +- packages/nextjs/src/server-only-stubs.ts | 18 ++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 packages/nextjs/src/__tests__/auth-misimport.test.ts create mode 100644 packages/nextjs/src/server-only-stubs.ts diff --git a/packages/nextjs/src/__tests__/auth-misimport.test.ts b/packages/nextjs/src/__tests__/auth-misimport.test.ts new file mode 100644 index 00000000000..8e9f3813be1 --- /dev/null +++ b/packages/nextjs/src/__tests__/auth-misimport.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from 'vitest'; + +import { auth } from '../server-only-stubs'; + +describe('auth misimport from @clerk/nextjs', () => { + it('throws a descriptive error when called as a function', () => { + expect(() => (auth as unknown as () => void)()).toThrow("Clerk: auth() was imported from '@clerk/nextjs'"); + expect(() => (auth as unknown as () => void)()).toThrow("import { auth } from '@clerk/nextjs/server'"); + }); + + it('throws a descriptive error when accessing a property', () => { + expect(() => (auth as unknown as Record).protect).toThrow( + "Clerk: auth was imported from '@clerk/nextjs'", + ); + expect(() => (auth as unknown as Record).protect).toThrow( + "import { auth } from '@clerk/nextjs/server'", + ); + }); +}); diff --git a/packages/nextjs/src/index.ts b/packages/nextjs/src/index.ts index 283a7935cfc..18c5b686352 100644 --- a/packages/nextjs/src/index.ts +++ b/packages/nextjs/src/index.ts @@ -96,4 +96,4 @@ export const Show = ComponentsModule.Show as ServerComponentsServerModuleTypes[' * The `auth` function is only available in server-side contexts: * API Routes, Server Components, Server Actions, and Middleware. */ -export declare const auth: never; +export { auth } from './server-only-stubs'; diff --git a/packages/nextjs/src/server-only-stubs.ts b/packages/nextjs/src/server-only-stubs.ts new file mode 100644 index 00000000000..725e58c9b34 --- /dev/null +++ b/packages/nextjs/src/server-only-stubs.ts @@ -0,0 +1,18 @@ +/** + * Runtime stubs for server-only exports that are accidentally imported from the + * main `@clerk/nextjs` entry point. Each stub is a Proxy that throws a + * descriptive error pointing the developer to the correct import path. + */ + +export const auth: never = new Proxy((() => {}) as never, { + apply() { + throw new Error( + `Clerk: auth() was imported from '@clerk/nextjs'. The auth() helper is a server-side function and must be imported from '@clerk/nextjs/server'.\n\nTo fix this, update your import:\n import { auth } from '@clerk/nextjs/server'`, + ); + }, + get() { + throw new Error( + `Clerk: auth was imported from '@clerk/nextjs'. The auth() helper is a server-side function and must be imported from '@clerk/nextjs/server'.\n\nTo fix this, update your import:\n import { auth } from '@clerk/nextjs/server'`, + ); + }, +}); From 7e031ec07eecb2508496475b21eb0a0a37699b2f Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Wed, 6 May 2026 10:54:43 -0400 Subject: [PATCH 2/3] chore: add changeset for auth misimport error Co-Authored-By: Claude Opus 4.6 --- .changeset/auth-misimport-runtime-error.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/auth-misimport-runtime-error.md diff --git a/.changeset/auth-misimport-runtime-error.md b/.changeset/auth-misimport-runtime-error.md new file mode 100644 index 00000000000..26355f119b8 --- /dev/null +++ b/.changeset/auth-misimport-runtime-error.md @@ -0,0 +1,5 @@ +--- +"@clerk/nextjs": patch +--- + +Improved error message when `auth` is accidentally imported from `@clerk/nextjs` instead of `@clerk/nextjs/server`. Previously, bundlers would show a generic `'auth' is not exported` error. Now, a clear runtime error points developers to the correct import path. From 140d3345c9f0c9db326e96b5d6142159ee09b0cb Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Thu, 7 May 2026 08:16:31 -0400 Subject: [PATCH 3/3] change approach to jsdoc @deprecated notice --- .changeset/auth-misimport-runtime-error.md | 2 +- .../src/__tests__/auth-misimport.test.ts | 19 ------------------- packages/nextjs/src/index.ts | 4 ++-- packages/nextjs/src/server-only-stubs.ts | 18 ------------------ 4 files changed, 3 insertions(+), 40 deletions(-) delete mode 100644 packages/nextjs/src/__tests__/auth-misimport.test.ts delete mode 100644 packages/nextjs/src/server-only-stubs.ts diff --git a/.changeset/auth-misimport-runtime-error.md b/.changeset/auth-misimport-runtime-error.md index 26355f119b8..7fd05b556a3 100644 --- a/.changeset/auth-misimport-runtime-error.md +++ b/.changeset/auth-misimport-runtime-error.md @@ -2,4 +2,4 @@ "@clerk/nextjs": patch --- -Improved error message when `auth` is accidentally imported from `@clerk/nextjs` instead of `@clerk/nextjs/server`. Previously, bundlers would show a generic `'auth' is not exported` error. Now, a clear runtime error points developers to the correct import path. +Improved developer experience when `auth` is accidentally imported from `@clerk/nextjs` instead of `@clerk/nextjs/server`. The `auth` export now includes a `@deprecated` JSDoc tag with a clear message guiding developers to the correct import path, visible on hover in IDEs. diff --git a/packages/nextjs/src/__tests__/auth-misimport.test.ts b/packages/nextjs/src/__tests__/auth-misimport.test.ts deleted file mode 100644 index 8e9f3813be1..00000000000 --- a/packages/nextjs/src/__tests__/auth-misimport.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { describe, expect, it } from 'vitest'; - -import { auth } from '../server-only-stubs'; - -describe('auth misimport from @clerk/nextjs', () => { - it('throws a descriptive error when called as a function', () => { - expect(() => (auth as unknown as () => void)()).toThrow("Clerk: auth() was imported from '@clerk/nextjs'"); - expect(() => (auth as unknown as () => void)()).toThrow("import { auth } from '@clerk/nextjs/server'"); - }); - - it('throws a descriptive error when accessing a property', () => { - expect(() => (auth as unknown as Record).protect).toThrow( - "Clerk: auth was imported from '@clerk/nextjs'", - ); - expect(() => (auth as unknown as Record).protect).toThrow( - "import { auth } from '@clerk/nextjs/server'", - ); - }); -}); diff --git a/packages/nextjs/src/index.ts b/packages/nextjs/src/index.ts index 18c5b686352..adf5fca7751 100644 --- a/packages/nextjs/src/index.ts +++ b/packages/nextjs/src/index.ts @@ -85,7 +85,7 @@ export const ClerkProvider = ComponentsModule.ClerkProvider as ServerComponentsS export const Show = ComponentsModule.Show as ServerComponentsServerModuleTypes['Show']; /** - * `auth` is not available from this import path. + * @deprecated `auth()` must be imported from `@clerk/nextjs/server`, not `@clerk/nextjs`. * * **To fix this error:** * ```diff @@ -96,4 +96,4 @@ export const Show = ComponentsModule.Show as ServerComponentsServerModuleTypes[' * The `auth` function is only available in server-side contexts: * API Routes, Server Components, Server Actions, and Middleware. */ -export { auth } from './server-only-stubs'; +export declare const auth: never; diff --git a/packages/nextjs/src/server-only-stubs.ts b/packages/nextjs/src/server-only-stubs.ts deleted file mode 100644 index 725e58c9b34..00000000000 --- a/packages/nextjs/src/server-only-stubs.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Runtime stubs for server-only exports that are accidentally imported from the - * main `@clerk/nextjs` entry point. Each stub is a Proxy that throws a - * descriptive error pointing the developer to the correct import path. - */ - -export const auth: never = new Proxy((() => {}) as never, { - apply() { - throw new Error( - `Clerk: auth() was imported from '@clerk/nextjs'. The auth() helper is a server-side function and must be imported from '@clerk/nextjs/server'.\n\nTo fix this, update your import:\n import { auth } from '@clerk/nextjs/server'`, - ); - }, - get() { - throw new Error( - `Clerk: auth was imported from '@clerk/nextjs'. The auth() helper is a server-side function and must be imported from '@clerk/nextjs/server'.\n\nTo fix this, update your import:\n import { auth } from '@clerk/nextjs/server'`, - ); - }, -});