Clerk: redirect loop after authentication [2026 fix]
Redirect loop caused by mismatched callback URL or missing signUpUrl/signInUrl props. Add exact domain to Clerk dashboard + configure routing props.
Clerk: Redirect Loop After Authentication [2am Emergency Fix]
TL;DR
Cause: Your Clerk dashboard callback URL doesn't match your app's actual domain, or<ClerkProvider> is missing signUpUrl/signInUrl props.
Fix: Update callback URL in Clerk dashboard to exact domain + add routing configuration to ClerkProvider.---
Exact Error Messages from Console
You'll see one or more of these:
``` Error: Redirect loop detected at redirectToSignIn (clerk.browser.js:4521:15) ```
``` warning: The <ClerkProvider> component does not have the signUpUrl prop. Please ensure you've set up your authentication URLs correctly. ```
``` GET http://localhost:3000/auth/callback?code=code_xxx 301 Moved Permanently → http://localhost:3000/auth/callback ```
``` Error: Cannot read property 'redirectUrl' of undefined at handleRedirectCallback (clerk.esm.js:8934:22) ```
``` warning: Clerk session is not ready yet. Skipping redirect. (infinite loop of this message) ```
---
The Problem: Broken Code
Scenario 1: Missing routing props on ClerkProvider
```jsx // ❌ BROKEN - redirect loop happens here import { ClerkProvider } from '@clerk/nextjs';
export default function RootLayout({ children }) { return ( <ClerkProvider> <html> <body>{children}</body> </html> </ClerkProvider> ); } ```
Scenario 2: Callback URL mismatch in dashboard
``` ❌ BROKEN in Clerk Dashboard: Callback URLs: http://localhost:3000/auth/callback Redirect URL (app): http://127.0.0.1:3000/auth/callback ↑ Different localhost vs 127.0.0.1 = infinite redirect ```
Scenario 3: Sign-in component without proper routing
```jsx // ❌ BROKEN - after authentication, nowhere to redirect to import { SignIn } from '@clerk/nextjs';
export default function LoginPage() { return <SignIn />; // Missing fallbackRedirectUrl } ```
---
The Fix: Exact Code Changes
Fix 1: Add routing props to ClerkProvider
```jsx // ✅ FIXED - routes properly configured import { ClerkProvider } from '@clerk/nextjs';
export default function RootLayout({ children }) { return ( <ClerkProvider signInUrl="/sign-in" signUpUrl="/sign-up" afterSignInUrl="/dashboard" afterSignUpUrl="/onboarding" > <html> <body>{children}</body> </html> </ClerkProvider> ); } ```
Fix 2: Update Clerk Dashboard callback URL
``` ✅ FIXED in Clerk Dashboard: Callback URLs: http://localhost:3000 https://yourdomain.com https://www.yourdomain.com ↑ Use EXACT domain your app runs on (no /auth/callback suffix needed) ```
Navigate to: Clerk Dashboard → Applications → [Your App] → Advanced → Allowed callback URLs
Fix 3: Add fallback redirect to SignIn component
```jsx // ✅ FIXED - explicit redirect path import { SignIn } from '@clerk/nextjs';
export default function LoginPage() { return ( <SignIn fallbackRedirectUrl="/dashboard" signUpUrl="/sign-up" /> ); } ```
Fix 4: Environment variables check
```bash
✅ FIXED - verify these exist in .env.local
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxx CLERK_SECRET_KEY=sk_test_xxxxx NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/onboarding ```---
Still Broken? Check These Too
1. Middleware routing conflict — If using middleware.ts in Next.js, ensure it doesn't redirect authenticated users back to /sign-in. Check that your publicRoutes array includes /sign-in and /sign-up.
2. Custom domain + localhost mismatch — Are you testing on localhost:3000 but Clerk dashboard only has production domain? Add http://localhost:3000 as callback URL for local development separately.
3. Session not yet loaded — The warning "session is not ready yet" means your redirect is firing before useAuth() hook completes. Wrap redirects in useEffect with isLoaded check from useClerk().
---
Version Note
These instructions apply to Clerk v4.x–v5.x (2025–2026). If using Clerk v3 or earlier, the @clerk/nextjs package structure differs slightly. Check your package.json version before applying.
---
Related Guides
---
Official Documentation
[Clerk Next.js Setup Guide](https://clerk.com/docs/quickstarts/nextjs)
---
Found a different variation? Drop it in the comments
If you hit a redirect loop with a different stack (React, Vue, Remix) or hit this after updating Clerk versions, share the exact error message and setup in comments. This guide will be updated with additional scenarios.