Clerk: redirect loop after authentication [2026 fix]

Clerk redirect loops occur when afterSignInUrl or afterSignUpUrl point to protected routes without proper middleware. Fix: ensure redirect URLs are public or add signInUrl/signUpUrl to your Clerk config.

TL;DR

Cause: Your afterSignInUrl or afterSignUpUrl redirects to a protected route, which re-triggers Clerk's auth check, creating an infinite loop.

Fix: Point redirects to public pages, or configure signInUrl/signUpUrl in your Clerk middleware to handle unauthenticated traffic correctly.

---

Real Console Error Messages

Watch your browser console and server logs for these exact patterns:

``` Error: Maximum call stack size exceeded ```

``` GET /dashboard 307 (Temporary Redirect) GET /sign-in 307 (Temporary Redirect) GET /dashboard 307 (Temporary Redirect) ```

``` TypeError: Cannot read properties of undefined (reading 'userId') ```

``` ClerkInstanceContext is undefined. Make sure you are using <ClerkProvider> ```

``` Warning: React does not recognize the 'clerkRedirectUrl' prop on a DOM element ```

---

Broken Code → Fixed Code

Problem 1: Redirect Loop in Clerk Config

BROKEN: ```javascript // clerkConfig.js export const clerkConfig = { afterSignInUrl: '/dashboard', afterSignUpUrl: '/onboarding', signInUrl: '/sign-in', };

// middleware.ts import { authMiddleware } from '@clerk/nextjs';

export const middleware = authMiddleware({ publicRoutes: ['/'], ignoredRoutes: ['/api/webhooks/clerk'], }); ```

The issue: /dashboard is NOT in publicRoutes, so after sign-in succeeds, Clerk redirects to /dashboard, the middleware blocks it, redirects back to /sign-in, and the cycle repeats.

FIXED: ```javascript // clerkConfig.js export const clerkConfig = { afterSignInUrl: '/welcome', // public page afterSignUpUrl: '/onboarding', // public page signInUrl: '/sign-in', };

// middleware.ts import { authMiddleware } from '@clerk/nextjs';

export const middleware = authMiddleware({ publicRoutes: ['/', '/welcome', '/onboarding', '/sign-in', '/sign-up'], ignoredRoutes: ['/api/webhooks/clerk'], });

export const config = { matcher: ['/((?!.*\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'], }; ```

---

Problem 2: useUser() Hook in Non-Protected Context

BROKEN: ```javascript // pages/dashboard.tsx import { useUser } from '@clerk/nextjs';

export default function Dashboard() { const { user, isLoaded } = useUser(); // This runs before user context is ready if (!user) return <Redirect to="/sign-in" />; return <h1>Welcome, {user.firstName}</h1>; } ```

FIXED: ```javascript // pages/dashboard.tsx import { useUser, withProtectedPage } from '@clerk/nextjs';

function Dashboard() { const { user, isLoaded } = useUser(); if (!isLoaded) return <LoadingSpinner />; if (!user) return null; // Clerk already redirected return <h1>Welcome, {user.firstName}</h1>; }

export default withProtectedPage(Dashboard); // OR: export const getServerSideProps = withPageAuthRequired(); ```

---

Problem 3: Missing ClerkProvider Wrapper

BROKEN: ```javascript // _app.tsx export default function App({ Component, pageProps }) { return <Component {...pageProps} />; } ```

FIXED: ```javascript // _app.tsx import { ClerkProvider } from '@clerk/nextjs';

export default function App({ Component, pageProps }) { return ( <ClerkProvider> <Component {...pageProps} /> </ClerkProvider> ); } ```

---

Still Broken? Check These Too

1. Env vars missing or wrong: Verify NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY exist in .env.local. Restart your dev server after adding them.

2. Stale build cache: Run npm run build --force and clear .next/. Old middleware bytecode can cause phantom redirects.

3. Session token expired during redirect: If your auth flow takes >15 seconds, the session token expires mid-redirect. Check network throttling in DevTools and increase Clerk's token TTL in [your dashboard](https://dashboard.clerk.com).

---

Version Note

This guide covers Clerk SDK v5+ (2024–2026). If you're on v4, the middleware API differs; check your installed version with npm list @clerk/nextjs. Behavior described here applies to Next.js 13+ with App Router. [See our middleware guide](/?guide=clerk-middleware-setup) for Pages Router differences.

---

Related Reading

  • [Clerk authentication state management best practices](/?guide=clerk-useauth)
  • [Common Next.js middleware pitfalls](/?guide=nextjs-middleware-errors)
  • Official Resources

  • [Clerk Next.js documentation](https://clerk.com/docs/nextjs)
  • [Clerk middleware reference](https://clerk.com/docs/references/nextjs/auth-middleware)
  • ---

    Found a different variation? Drop it in the comments—we update this guide based on real production issues.

    🔥 0d
    LIVE
    ↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising •↑ Resend loved by devs •↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising
    DEVELOPER PAIN RADAR // Loading...

    Developers complain.
    Opportunities appear.

    We track what developers are struggling with today — and what opportunities that creates.

    —
    guides today
    —
    avg happiness
    🔥 Pain
    📖 Guides
    🔭 Explore
    👤 Mine
    🔥 Pain Radar — rage scores today
    ↗ share
    💡 Opportunity Feed — pain = market gap
    📈 Tool Momentum
    all scores →
    📖 Latest Guide
    all guides →
    📖 All Guides
    📊 Tool Scores
    + Submit
    📰 Hacker News
    ➕ Submit a Tool
    ← back