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