Clerk: redirect loop after authentication [2026 fix]
Redirect URI mismatch or missing signUpUrl causes infinite loop. Add exact redirect URIs to Clerk dashboard + configure signUpUrl in middleware.
Clerk: Redirect Loop After Authentication [2am Fix]
TL;DR
Cause: Your redirect URI in Clerk dashboard doesn't match your app's actual callback URL, orsignUpUrl is missing from your middleware configuration.Fix: Add http://localhost:3000/auth/callback (dev) and https://yourdomain.com/auth/callback (prod) to Clerk dashboard under "Redirect URLs," then set signUpUrl explicitly in your ClerkProvider or middleware.
---
Exact Error Messages You'll See
``` 1. "Error: Invalid redirect_uri. The redirect_uri parameter does not match any of the configured redirect URIs for this application."
2. "GET /auth/callback?code=xyz&state=abc 307 - Redirect loop detected"
3. "[Clerk] Redirect called but destination URL is not whitelisted"
4. "Error: The redirect URL is missing the signUpUrl configuration. Redirecting to sign-up but no URL found."
5. "POST /api/auth/callback - ERR_TOO_MANY_REDIRECTS" ```
---
Broken Code vs. Exact Fix
Issue 1: Missing Redirect URIs in Dashboard
❌ BROKEN (implicit, nothing in code—it's a config issue) ```javascript // Your app redirects to this after auth: // http://localhost:3000/auth/callback
// But Clerk dashboard has NO redirect URIs configured // or only has: http://localhost:3000 ```
✅ FIXED ``` Clerk Dashboard → Applications → [Your App] → Redirect URLs
Add BOTH:
Save and wait 30 seconds for propagation. ```
Issue 2: Missing signUpUrl in ClerkProvider
❌ BROKEN ```javascript // pages/_app.tsx or app/layout.tsx import { ClerkProvider } from '@clerk/nextjs';
export default function MyApp({ Component, pageProps }) { return ( <ClerkProvider> <Component {...pageProps} /> </ClerkProvider> ); } ```
✅ FIXED ```javascript import { ClerkProvider } from '@clerk/nextjs';
export default function MyApp({ Component, pageProps }) { return ( <ClerkProvider signUpUrl="/sign-up" signInUrl="/sign-in" afterSignInUrl="/dashboard" afterSignUpUrl="/onboarding" > <Component {...pageProps} /> </ClerkProvider> ); } ```
Issue 3: Middleware Redirect Misconfiguration
❌ BROKEN ```javascript // middleware.ts import { authMiddleware } from '@clerk/nextjs';
export const config = { matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'] };
export default authMiddleware(); ```
✅ FIXED ```javascript // middleware.ts import { authMiddleware } from '@clerk/nextjs';
export const config = { matcher: [ '/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)', '/(auth)(.*)' // Explicitly allow auth routes ] };
export default authMiddleware({ publicRoutes: [ '/sign-in', '/sign-up', '/auth/callback', // Add this line '/', '/api/public(.*)' ], ignoredRoutes: ['/api/webhooks(.*)'] }); ```
---
Step-by-Step Resolution at 2am
1. Check Clerk Dashboard (5 min)
- Go to https://dashboard.clerk.com
- Select your application
- Under "API Keys & URLs," verify "Redirect URLs" section
- Your localhost entry should be http://localhost:3000/auth/callback exactly
- Production entry should match your actual domain
2. Clear Browser Cache (2 min)
```bash
# Windows: Ctrl+Shift+Delete
# Mac: Cmd+Shift+Delete in Chrome, Cmd+Option+E in Safari
# Or in code:
```
Delete __session and __clerk_db_jwt cookies manually
3. Check Environment Variables (3 min) ```bash # .env.local must have: NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... 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 ```
4. Restart Dev Server (1 min) ```bash npm run dev # or yarn dev ```
---
Still Broken? Check These Too
1. CORS/Cookie Domain Mismatch — If testing across subdomains (api.example.com vs app.example.com), Clerk cookies won't match. Set cookieDomain in Clerk instance config: [CORS troubleshooting guide](/?guide=clerk-cors)
2. Stale Clerk Cache — Clerk caches redirect URIs for ~5 minutes. If you just updated the dashboard, wait 5 minutes and clear browser cache again. Force-refresh with Ctrl+Shift+R.
3. Auth Callback Route Missing — Ensure you have /auth/callback route implemented. In Next.js App Router: create app/auth/callback/route.ts with export const GET = handleClerkCallback(). In Pages Router: create pages/auth/callback.tsx with empty component. [Callback route setup](/?guide=clerk-callback-route)
4. Multiple Clerk Instances — If using Clerk in multiple places without shared context, each creates separate sessions. Use single <ClerkProvider> wrapper at root only.
5. Outdated @clerk/nextjs Package — Version 4.x+ has breaking changes. Check: npm list @clerk/nextjs. If below 4.25.0, update: npm install @clerk/nextjs@latest
---
Official Documentation
[Clerk Next.js Authentication Redirect Setup](https://clerk.com/docs/quickstarts/nextjs)---
Found a different variation? Drop it in the comments below.
If your redirect loop manifests differently (e.g., infinite/sign-in loops, custom domain issues, or API-based auth), reply with:
Helps us catch edge cases!