Clerk: redirect loop after authentication [2026 fix]
Redirect loop after Clerk auth caused by misconfigured callback URLs or stale session state. Fix: verify CLERK_REDIRECT_URL matches your domain exactly.
Clerk: Redirect Loop After Authentication – Emergency Fix
TL;DR
Cause: Callback URL in Clerk dashboard doesn't match your actual domain or middleware is redirecting authenticated users back to login. Fix: SetCLERK_REDIRECT_URL to your exact production domain (with protocol) and ensure your auth middleware only redirects *unauthenticated* users.---
Real Console Error Messages
Look for these exact errors in your browser console and server logs at 2am:
``` 1. ERR_TOO_MANY_REDIRECTS: Redirect loop detected. The page isn't redirecting properly.
2. Uncaught (in promise) Error: Redirect loop - user authenticated but redirected to /sign-in
3. GET http://localhost:3000/sign-in 302 Found → http://localhost:3000/sign-in (infinite redirect)
4. [Clerk] Redirect URL mismatch: expected https://example.com/auth/callback, got http://example.com/auth/callback
5. useAuth() returned isLoaded: false after successful authentication - session stale ```
---
Broken Code vs. Exact Fix
Problem 1: Wrong Callback URL
BROKEN: ```javascript // .env.local (wrong - using localhost for production) CLERK_PUBLISHABLE_KEY=pk_live_... CLERK_SECRET_KEY=sk_live_... CLERK_REDIRECT_URL=http://localhost:3000/auth/callback ```
FIXED: ```javascript // .env.local (correct - matches production domain exactly) CLERK_PUBLISHABLE_KEY=pk_live_... CLERK_SECRET_KEY=sk_live_... CLERK_REDIRECT_URL=https://yourdomain.com/auth/callback ```
Problem 2: Middleware Redirecting Authenticated Users
BROKEN: ```javascript // middleware.ts - redirects everyone to sign-in export default clerkMiddleware(async (auth, req) => { const { userId } = await auth(); // BUG: redirects even if authenticated if (!req.nextUrl.pathname.startsWith('/sign-in')) { return NextResponse.redirect(new URL('/sign-in', req.url)); } }); ```
FIXED: ```javascript // middleware.ts - only redirect unauthenticated users export default clerkMiddleware(async (auth, req) => { const { userId } = await auth(); const protectedRoutes = ['/dashboard', '/profile', '/settings']; if (!userId && protectedRoutes.some(route => req.nextUrl.pathname.startsWith(route))) { return NextResponse.redirect(new URL('/sign-in', req.url)); } });
export const config = { matcher: [ '/((?!_next/static|_next/image|favicon.ico|public).*)', ], }; ```
Problem 3: Stale Session After Sign-In
BROKEN: ```javascript // pages/dashboard.tsx - checking session too early import { useAuth } from '@clerk/nextjs';
export default function Dashboard() { const { userId, isLoaded } = useAuth(); // BUG: component renders before isLoaded is true if (!userId) return <Redirect to="/sign-in" />; return <div>Welcome {userId}</div>; } ```
FIXED: ```javascript // pages/dashboard.tsx - wait for session hydration import { useAuth } from '@clerk/nextjs'; import { useRouter } from 'next/navigation';
export default function Dashboard() { const { userId, isLoaded } = useAuth(); const router = useRouter(); // FIXED: only render after auth state is loaded if (!isLoaded) { return <div>Loading authentication...</div>; } if (!userId) { router.push('/sign-in'); return null; } return <div>Welcome {userId}</div>; } ```
---
Verification Checklist
1. Dashboard callback URLs (https://dashboard.clerk.com):
- Go to Settings → Application URLs
- Verify "Redirect URLs" includes: https://yourdomain.com/auth/callback
- For development: also add http://localhost:3000/auth/callback
2. Environment variables: ```bash echo $CLERK_REDIRECT_URL # should show your production domain ```
3. Middleware order: - Clerk middleware must run *before* your auth checks - NextAuth/sessions middleware conflict? Remove competing auth.
---
Still Broken? Check These Too
1. Mixed HTTP/HTTPS:
- Clerk live keys only work on HTTPS
- If your dashboard uses HTTPS but callback is HTTP, it fails silently
- Always use https://yourdomain.com
2. Multiple Auth Providers Conflict:
- Check if you have NextAuth + Clerk both active
- Remove one: [NextAuth + Clerk guide](/?guide=nextauth-clerk-conflict)
- Ensure only one auth middleware is exported from /middleware.ts
3. Session Cookie Domain Mismatch:
- If running on subdomain (api.example.com), Clerk may not persist session
- Verify CLERK_COOKIE_DOMAIN=example.com in production
- Browser DevTools → Application → Cookies → check __clerk_* cookies exist
---
Version Uncertainty
Note: This guide covers @clerk/nextjs v4.x and v5.x (2024-2026). The middleware API changed significantly between v3 and v4. If you're on v3, the clerkMiddleware() syntax differs—consult the [v3 migration docs](https://clerk.com/docs/upgrade-guides/nextjs).
---
Resources
---
Found a different variation? Drop it in the comments—redirect loops have creative new causes every month. Tag your Clerk version + framework when reporting.
---
*Last updated: 2026 | Still stuck at 3am? Check Clerk's status page or file an issue with exact redirect chain from DevTools Network tab.*