Clerk: redirect loop after authentication [2026 fix]

Redirect loop after Clerk auth caused by misconfigured middleware or stale session state. Clear cookies and fix middleware ordering.

Clerk: Redirect Loop After Authentication - 2am Emergency Fix

TL;DR

Cause: Clerk middleware runs after your auth check redirect, or session cookies aren't being set properly due to domain/secure flag mismatch. Fix: Reorder middleware so Clerk runs first, then verify NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY matches your domain config.

---

Exact Error Messages from Console

You'll likely see one or more of these:

``` Error: Redirect loop detected. The page at 'https://yourapp.com/dashboard' redirected to 'https://yourapp.com/sign-in' which redirected back to 'https://yourapp.com/dashboard' ```

``` [Clerk] Error: Unable to load user. Session cookie not found or invalid. Code: session_not_found ```

``` warning: Clerk session validation failed at middleware layer - user object undefined after auth callback ```

``` TypeError: Cannot read property 'id' of undefined at /app/middleware.ts:15:12 ```

``` [Next.js] Infinite redirect detected - middleware condition not met after authentication ```

---

Broken Code vs. Exact Fix

Problem #1: Middleware Execution Order (Most Common)

BROKEN: ```typescript // middleware.ts - WRONG ORDER import { authMiddleware } from "@clerk/nextjs/server";

export const middleware = (req: NextRequest) => { // Your custom redirect runs BEFORE Clerk sets up the session if (req.nextUrl.pathname === "/dashboard" && !hasAuth) { return NextResponse.redirect(new URL("/sign-in", req.url)); } // Clerk runs AFTER - too late to catch the redirect return authMiddleware()(req); };

export const config = { matcher: ["/((?!_next|static).*)"], }; ```

FIXED: ```typescript // middleware.ts - CORRECT ORDER import { authMiddleware } from "@clerk/nextjs/server"; import { NextResponse } from "next/server"; import type { NextRequest } from "next/server";

export const middleware = authMiddleware((auth, req) => { // Clerk runs FIRST and populates auth state // THEN your logic runs with valid session if (req.nextUrl.pathname === "/dashboard" && !auth().userId) { return NextResponse.redirect(new URL("/sign-in", req.url)); } });

export const config = { matcher: [ // Exclude static assets and Clerk's own routes "/((?!_next|static|.*\\.png|.*\\.jpg|/sign-in|/sign-up).*)", ], }; ```

Problem #2: Environment Variable Domain Mismatch

BROKEN: ```bash

.env.local - domain doesn't match actual deployment

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xyz123 CLERK_SECRET_KEY=sk_test_abc789 NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in

Missing or wrong domain configuration in Clerk Dashboard

```

FIXED: ```bash

.env.local - must match Clerk Dashboard + actual domain

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xyz123 CLERK_SECRET_KEY=sk_test_abc789 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 ```

Then in Clerk Dashboard → Settings → URLs, verify:

  • Allowed redirect URLs includes: https://yourapp.com
  • Sign-in URL: https://yourapp.com/sign-in
  • API URL matches your deployment domain exactly
  • Problem #3: Session Cookie Not Persisting

    BROKEN: ```typescript // middleware.ts - doesn't preserve session const isAuth = async (req) => { const token = req.cookies.get("__session")?.value; if (!token) return false; // Session lost on redirect }; ```

    FIXED: ```typescript // middleware.ts - use Clerk's native session handling import { getAuth } from "@clerk/nextjs/server";

    export const middleware = authMiddleware((auth, req) => { // Clerk handles session persistence automatically const { userId } = auth(); // Session cookie managed by Clerk with correct secure/sameSite flags }); ```

    ---

    Still Broken? Check These Too

    1. Stale Browser Cache/Cookies: Open DevTools → Application → Cookies. Delete all cookies for your domain, then hard refresh (Cmd+Shift+R / Ctrl+Shift+R). Expired __session cookies cause immediate re-auth loops.

    2. Next.js Build Mismatch: Run rm -rf .next && npm run build then restart. Cached build artifacts can reference old middleware logic.

    3. Multiple Auth Providers Conflict: If using both Clerk AND NextAuth or Auth0, check that only ONE middleware is active. Remove conflicting authMiddleware() calls. See our [guide on combining auth providers](/?guide=multi-auth).

    4. Localhost vs. Production Domain: Development works on localhost:3000 but production https://yourapp.com doesn't. Verify Clerk Dashboard has the production URL in Allowed redirect URLs. I'm uncertain if this varies by Clerk version; check your Dashboard version number before applying.

    5. API Route Protected Without Middleware: If protecting /api/* endpoints, ensure middleware matcher includes them OR use getAuth() inside each route handler. See [protecting API routes](/?guide=clerk-api-protection).

    ---

    One-Minute Diagnostic

    1. Open DevTools → Network tab → filter by /sign-in or /dashboard 2. Look for redirect chains (301/302 responses back-to-back) 3. Check Network → Cookies tab for __session — should exist after sign-in 4. Compare your middleware matcher against your actual routes 5. Clear browser cookies and try again

    ---

    Official Resources

  • [Clerk Middleware Documentation](https://clerk.com/docs/references/nextjs/middleware)
  • [Clerk Environment Variables Guide](https://clerk.com/docs/deployments/clerk-environment-variables)
  • [Clerk Dashboard Setup](https://dashboard.clerk.com)
  • ---

    Found a different variation? Drop it in the comments below — we update this guide based on your real 2am issues.

    🔥 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