āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š shadcn/directory/clerk/clerk-docs/reference/nextjs/errors/auth-was-called ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
This error occurs when a request that is not covered by clerkMiddleware() gets a 404 return in a Clerk + Next.js App Router setup.
This error commonly appears when using Clerk with Next.js and the clerkMiddleware() helper is configured not to run on static asset routes, which is part of the default setup. It can happen for the following reasons:
<ClerkProvider>: The <ClerkProvider> is not wrapped around the component tree where Clerk components are used.<ClerkProvider>The most common cause of this error is when auth() is called without a <ClerkProvider> wrapping the component tree where Clerk components are used.
Ensure that <ClerkProvider> is set up at a higher level in your component hierarchy than any Clerk components like <UserButton />, <SignedIn />, or others. The Next.js quickstart shows how you can do this in your root layout.
import { ClerkProvider } from '@clerk/nextjs'
import './globals.css'
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<ClerkProvider>
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
{children}
</body>
</html>
</ClerkProvider>
)
}
If <ClerkProvider> is correctly configured, it's possible this error is happening because when auth() was called, clerkMiddleware() didn't run on the request. This can occur if a request is made to a non-existent static asset. Static asset requests are excluded by the matcher Clerk provides and often from other proxy.ts matchers, so clerkMiddleware() doesn't run for them. A typo or incorrect path is usually the problem in these cases.
For example,
/dashboard, which is a valid page and matched route.<img> tag with a src pointing to an invalid path.<ClerkProvider> is usually placed in the root layout, it runs, but because the request didn't match the middleware matcher, clerkMiddleware() never executed. As a result, <ClerkProvider> attempts to call auth() without context, leading to one of these outcomes:
500 or 404 error in your browser's network tab.GET /{non-existing-path}.{static-asset-extension} 500 | 404 in your terminal or logs.x [Error: Clerk: auth() was called but Clerk can't detect usage of clerkMiddleware(). Please ensure the following:
Your Middleware exists at ./src/middleware.(ts|js)
clerkMiddleware() is used in your Next.js Middleware.
Your Middleware matcher is configured to match this route or page.
If you are using the src directory, make sure the Middleware file is inside of it.
For more details, see https://clerk.com/docs/quickstarts/nextjs
] {
digest: '3346914516'
}
Select the appropriate solution based on your use case:
<Tabs items={["Correct the static asset paths (recommended)", "Scope the <ClerkProvider> to a sub-layout"]}> <Tab> The ideal solution is to fix any incorrect asset paths, as this is the root cause of the error and the cleanest fix. Ensure that all images, icons, or files are requested using valid URLs. When these requests succeed, no 404 is triggered, and the Clerk provider context works as expected. </Tab>
<Tab> This fix will prevent _the Clerk error_, as it moves `<ClerkProvider>` from the root layout. However, it does not resolve the underlying issue, which is a reference to a missing static asset. Your app will still have a 404 network request for the missing asset.If you want to protect your app against similar issues in the future or want to ensure that system-level errors (like 404s) don't rely on Clerk, you can refactor your layout structure.
By moving `<ClerkProvider>` into a subfolder layout, you allow 404 pages and other global error routes to render without needing Clerk's context.
**Before**
```bash
app/
layout.ts // includes <ClerkProvider />
```
**After**
```bash
app/
layout.ts // base layout without Clerk
(in-app) // virtual folder - doesn't impact routing
layout.ts // includes <ClerkProvider />
page.tsx
```
Here's an example of what the new Clerk layout would look like in this case:
```tsx {{ filename: 'app/(in-app)/layout.tsx' }}
import { ClerkProvider } from '@clerk/nextjs'
export default function AppLayout({ children }: { children: React.ReactNode }) {
return <ClerkProvider>{children}</ClerkProvider>
}
```
Or loading Clerk built-in components:
```tsx {{ filename: 'app/(in-app)/layout.tsx' }}
import {
ClerkProvider,
SignedIn,
SignedOut,
SignInButton,
SignUpButton,
UserButton,
} from '@clerk/nextjs'
export default function AppLayout({ children }: { children: React.ReactNode }) {
return (
<ClerkProvider>
<header className="flex justify-end items-center p-4 gap-4 h-16">
<SignedOut>
<SignInButton />
<SignUpButton />
</SignedOut>
<SignedIn>
<UserButton />
</SignedIn>
</header>
{children}
</ClerkProvider>
)
}
```
This ensures the root layout (which handles top-level errors like 404s) does not rely on Clerk, avoiding the middleware mismatch error entirely.
</Tab>
</Tabs>ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā