Skip to main content

Clerk: auth() was called but Clerk can't detect usage of clerkMiddleware()

Clerk: auth() was called but Clerk can't detect usage of clerkMiddleware(). Please ensure the following:
clerkMiddleware() is used in your Next.js middleware or proxy file.
Your middleware or proxy matcher is configured to match this route or page.
If you are using the src directory, make sure the middleware or proxy file is inside of it.

If you've verified your configuration and are still seeing this error, there may be a runtime issue or a problem communicating with Clerk.

For more details, see https://clerk.com/err/auth-middleware

On Next.js 15 and earlier, the message says middleware in place of middleware or proxy.

Why this occurred

This error occurs when a request that isn't covered by clerkMiddleware() returns a 404 in a Clerk + Next.js App Router setup. It commonly appears when the clerkMiddleware()Next.js Icon helper is configured not to run on static asset routes, which is part of the default setup. It can happen for the following reasons:

  • Missing <ClerkProvider>: The <ClerkProvider> is not wrapped around the component tree where Clerk components are used.
  • Incorrect path: A typo or incorrect path is used in a static asset request.

Ways to fix this

Missing <ClerkProvider>

Choose this when <ClerkProvider> isn't wrapping the component tree where Clerk components are used. This is the most common cause — auth()Next.js Icon is called without a <ClerkProvider> above it in the tree.

The <ClerkProvider> component provides session and user context to Clerk's hooks and components. It's recommended to wrap your entire app at the entry point with <ClerkProvider> to make authentication globally accessible. See the reference docs for other configuration options.

Solution

Ensure that <ClerkProvider> is set up at a higher level in your component hierarchy than any Clerk components like <UserButton />, <Show>, or others. The Next.js quickstart shows how you can do this in your root layout.

app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs'
import { Geist, Geist_Mono } from 'next/font/google'
import './globals.css'

const geistSans = Geist({
  variable: '--font-geist-sans',
  subsets: ['latin'],
})

const geistMono = Geist_Mono({
  variable: '--font-geist-mono',
  subsets: ['latin'],
})

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode
}>) {
  return (
    <html lang="en" className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}>
      <body className="min-h-full flex flex-col">
        <ClerkProvider>{children}</ClerkProvider>
      </body>
    </html>
  )
}

Incorrect path

Choose this when <ClerkProvider> is configured correctly but a request still triggers the error. This happens 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 by other matchers in your Middleware, so clerkMiddleware() doesn't run for them. A typo or incorrect path is usually the problem in these cases.

For example,

  1. A user accesses /dashboard, which is a valid page and matched route.
  2. That page includes an <img> tag with a src pointing to an invalid path.
  3. A 404 error is triggered because of the invalid static asset request.
  4. Next.js serves the 404 response.
  5. The 404 page is rendered within the root layout — that's where Next.js injects their 404 page/component.
  6. Since <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:
    • A 500 or 404 error in your browser's network tab.
    • GET /{non-existing-path}.{static-asset-extension} 500 | 404 in your terminal or logs.
    • The following Clerk error in the console:
      x [Error: Clerk: auth() was called but Clerk can't detect usage of clerkMiddleware(). Please ensure the following:
      clerkMiddleware() is used in your Next.js middleware or proxy file.
      Your middleware or proxy matcher is configured to match this route or page.
      If you are using the src directory, make sure the middleware or proxy file is inside of it.
      
      If you've verified your configuration and are still seeing this error, there may be a runtime issue or a problem communicating with Clerk.
      
      For more details, see https://clerk.com/err/auth-middleware
      ] {
      digest: '3346914516'
      }

Solution

Select the appropriate solution based on your use case:

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.

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

app/
  layout.ts  // includes <ClerkProvider />

After

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:

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:

app/(in-app)/layout.tsx
import { ClerkProvider, Show, 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">
        <Show when="signed-out">
          <SignInButton />
          <SignUpButton />
        </Show>
        <Show when="signed-in">
          <UserButton />
        </Show>
      </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.

Feedback

What did you think of this content?

Last updated on