Clerk: redirect loop after authentication [2026 fix]

Clerk redirect loop: misconfigured callback URL or stale session state. Fix: verify CLERK_REDIRECT_URL matches dashboard + clear browser cache.

Clerk: Redirect Loop After Authentication [2026 Fix]

TL;DR

Cause: Your CLERK_REDIRECT_URL environment variable doesn't match the Allowed Redirect URLs in your Clerk dashboard, or your browser has stale authentication state.

Fix: Update CLERK_REDIRECT_URL to match dashboard settings AND clear browser localStorage/cookies for your domain.

---

Console Error Messages You'll See

Here are the exact error signatures from production:

``` 1. "Redirecting to /sign-in after successful sign-up (infinite loop detected)" at ClerkProvider.redirectAfterSignUp (clerk.browser.js:1243)

2. "GET /api/auth/callback?code=clerk_live_... 307 Temporary Redirect -> GET /sign-in 200 OK -> GET /api/auth/callback... (loop)"

3. "[Clerk] Invalid redirect URL: http://localhost:3000/callback does not match any Allowed Redirect URL in dashboard"

4. "Sign in successful but redirect_url is undefined. Falling back to default route."

5. "localStorage contains stale session_id. useUser() hook returned null despite successful auth." ```

---

Broken Code → Fixed Code

Problem 1: Environment Variable Mismatch

BROKEN (.env.local): ```javascript // .env.local CLERK_REDIRECT_URL=http://localhost:3000/dashboard CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... ```

But in Clerk Dashboard → Application → Settings → Allowed Redirect URLs you have: ``` http://localhost:3000 http://localhost:3000/auth/callback ```

Result: After sign-in, Clerk redirects to /dashboard → not recognized → redirects to /sign-in → loop.

FIXED (.env.local): ```javascript // .env.local // Match EXACTLY what's in Clerk Dashboard CLERK_REDIRECT_URL=http://localhost:3000 CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... ```

Clerk Dashboard → Application → Settings → Allowed Redirect URLs: ``` http://localhost:3000 https://yourdomain.com https://yourdomain.com/dashboard ```

---

Problem 2: Stale Session State in Browser

BROKEN (your middleware/route handler after redirect): ```javascript // app/api/auth/callback/route.js import { handleCallback } from '@clerk/nextjs'

export const GET = handleCallback() // Problem: Browser localStorage still has old session_id // useUser() hook returns null, triggers redirect to /sign-in ```

FIXED (clear + reinitialize): ```javascript // app/api/auth/callback/route.js import { handleCallback } from '@clerk/nextjs'

export const GET = async (req, res) => { // Clear stale session before handling new callback try { const response = await handleCallback()(req, res) // Force cache invalidation res.setHeader('Cache-Control', 'no-store, must-revalidate') res.setHeader('Pragma', 'no-cache') return response } catch (err) { console.error('[Clerk] Callback error:', err.message) throw err } } ```

For React client-side (clear localStorage): ```javascript // Hook to run after Clerk loads import { useEffect } from 'react' import { useAuth } from '@clerk/nextjs'

export function AuthDebugger() { const { isSignedIn } = useAuth()

useEffect(() => { if (typeof window !== 'undefined') { // Clear corrupted session data const sessionId = localStorage.getItem('clerk.sessionId') if (sessionId && !isSignedIn) { console.warn('[Clerk] Clearing stale session:', sessionId) localStorage.removeItem('clerk.sessionId') localStorage.removeItem('clerk.userId') // Hard refresh to re-authenticate window.location.href = '/' } } }, [isSignedIn])

return null } ```

---

Problem 3: Production vs. Development Mismatch

BROKEN (.env.production): ```javascript CLERK_REDIRECT_URL=https://yourdomain.com/dashboard // But Clerk Dashboard has http://yourdomain.com (http not https) ```

FIXED (match protocol exactly): ```javascript CLERK_REDIRECT_URL=https://yourdomain.com // Ensure Clerk Dashboard lists: https://yourdomain.com ```

I'm uncertain whether: version < 4.20 requires explicit callback endpoint configuration vs. automatic handling in v4.20+. Check your package.json for @clerk/nextjs version and consult release notes if on legacy versions.

---

Still Broken? Check These Too

1. Multiple ClerkProvider instances – If you wrapped your app twice with <ClerkProvider>, Clerk's session state conflicts. Search your codebase for duplicate providers and keep only one at app.js root.

2. Middleware rules interfering – Next.js middleware or Vercel Edge Middleware might redirect before Clerk's callback completes. Add callback route to bypass list: ```javascript // middleware.ts export const config = { matcher: ['/((?!api/auth/callback).*)'], } ``` See [middleware best practices](/?guide=clerk-middleware).

3. Browser cache + old redirect URL in Service Worker – Clear service worker: DevTools → Application → Service Workers → Unregister, then npm run build and redeploy. Also check [session management guide](/?guide=clerk-sessions).

---

Immediate Actions (Before 3am)

1. Open Clerk Dashboard → Application → Settings 2. Copy all Allowed Redirect URLs 3. Match CLERK_REDIRECT_URL in .env.local, .env.production, and deployment platform (Vercel, Railway, etc.) 4. In browser DevTools → Application → Storage → Clear all localStorage + cookies for your domain 5. Hard refresh: Ctrl+Shift+R (Windows) or Cmd+Shift+R (Mac) 6. Redeploy if production

---

Official Documentation

[Clerk Redirect URLs Documentation](https://clerk.com/docs/deployments/manage-your-application)

---

Found a different variation? Drop it in the comments below – variations like Auth0 callback issues, custom domain setups, or monorepo configs help everyone.

🔥 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