Clerk: redirect loop after authentication [2026 fix]

Redirect loop after Clerk auth caused by misconfigured callback URL or stale session state. Fix: Verify CLERK_REDIRECT_URL matches your domain and clear browser storage.

Clerk: Redirect Loop After Authentication [2am Emergency Fix]

TL;DR

Cause: Your Clerk redirect URL doesn't match your actual domain, or the session state is corrupted in browser storage. Fix: Set CLERK_REDIRECT_URL=https://yourdomain.com in .env.local and clear localStorage/sessionStorage in DevTools.

---

Real Console Error Messages

You'll see one or more of these exact errors:

``` Error: Redirect loop detected. Ensure CLERK_REDIRECT_URL is correctly configured. ```

``` undefined (reading 'redirectUrl') at AuthenticatedRoute.tsx:45 ```

``` warning: getAuth() returned null after redirect. Session may not be initialized. ```

``` [Clerk] Invalid redirect URI. Expected https://yourdomain.com but got http://localhost:3000 ```

``` Cookies are blocked or third-party cookies disabled. Auth session cannot persist. ```

---

Broken Code vs. Fixed Code

Problem 1: Missing or Mismatched Redirect URL

BROKEN: ```javascript // .env.local (WRONG - localhost only) CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... // CLERK_REDIRECT_URL is not set!

// pages/auth.tsx import { useAuth } from '@clerk/nextjs';

export default function AuthPage() { const { isSignedIn } = useAuth(); if (!isSignedIn) { return <SignInButton />; } return <Dashboard />; // Loops infinitely } ```

FIXED: ```javascript // .env.local (CORRECT - matches your actual domain) CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... CLERK_REDIRECT_URL=https://yourdomain.com NEXT_PUBLIC_CLERK_REDIRECT_URL=https://yourdomain.com

// pages/auth.tsx (with redirect guard) import { useAuth } from '@clerk/nextjs'; import { useRouter } from 'next/router'; import { useEffect } from 'react';

export default function AuthPage() { const { isSignedIn, isLoaded } = useAuth(); const router = useRouter(); useEffect(() => { if (isLoaded && isSignedIn) { router.push('/dashboard'); // Explicit redirect, not component return } }, [isLoaded, isSignedIn, router]); if (!isLoaded) return <div>Loading...</div>; if (isSignedIn) return null; // Return nothing while redirecting return <SignInButton />; } ```

Problem 2: Stale Session State in Browser

BROKEN: ```javascript // Middleware caches old session before env var was updated // middleware.ts import { authMiddleware } from '@clerk/nextjs';

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

export default authMiddleware(); // This uses cached redirectUrl from old environment ```

FIXED: ```javascript // middleware.ts - with explicit redirect handling import { authMiddleware, redirectToSignIn } from '@clerk/nextjs';

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

export default authMiddleware({ publicRoutes: ['/'], afterAuth(auth, req) { // If not authenticated and trying to access protected route if (!auth.userId && !auth.isPublicRoute) { return redirectToSignIn({ returnBackUrl: req.url }); } }, }); ```

THEN: In your browser DevTools (F12 → Application tab): ```javascript // Clear all Clerk-related storage Object.keys(localStorage).forEach(key => { if (key.includes('clerk') || key.includes('__clerk')) { localStorage.removeItem(key); } }); Object.keys(sessionStorage).forEach(key => { if (key.includes('clerk')) { sessionStorage.removeItem(key); } }); // Then reload page location.reload(); ```

---

Still Broken? Check These Too

1. Third-party cookies blocked in browser – Clerk requires cookies. Check DevTools → Settings → Cookies and disable "Block third-party cookies" for testing. For production, add your domain to allow list. See [related cookie debugging guide](/?guide=cookies).

2. Development vs. production mismatch – If CLERK_REDIRECT_URL=https://yourdomain.com but your app is on subdomain.yourdomain.com, Clerk rejects it as invalid. Update env var to match exactly, including subdomain. I'm uncertain if Clerk v0.19+ allows wildcard subdomains; check official docs.

3. SignInButton/SignUpButton missing callback prop – Some versions require explicit redirectUrl prop. Test with: <SignInButton redirectUrl="/dashboard" />. This behavior may vary between versions. See [authentication flow debugging](/?guide=auth-flow).

---

Found a Different Variation?

Drop it in the comments below! We update this guide based on real 2am incidents. Please include: (1) your Clerk SDK version, (2) exact error message, (3) your framework/version.

---

Official Resources

  • [Clerk Redirect URL Configuration](https://clerk.com/docs/deployments/configure-sign-in-redirect)
  • [Clerk NextJS Integration Guide](https://clerk.com/docs/quickstarts/nextjs)
  • [Session & Auth Middleware Docs](https://clerk.com/docs/references/nextjs/auth-middleware)
  • 🔥 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