Next.js ERR_TOO_MANY_REDIRECTS: Fix Middleware Loops

Browser says 'redirected you too many times' after adding auth middleware? The 5 real causes of Next.js redirect loops and how to break each one.

ERR_TOO_MANY_REDIRECTS in Next.js almost always means middleware (or a proxy in front of it) redirects a request to a URL that triggers the same redirect again; the fix is to exclude the destination from the matcher or add an explicit "already there" check.

The browser gives up after about 20 hops and shows "This page isn't working. localhost redirected you too many times." Users see a blank error page, and you see nothing in your error tracker because no JavaScript ever ran.

The Classic Auth Loop

// middleware.ts: broken
export function middleware(req: NextRequest) {
  const token = req.cookies.get('session')
  if (!token) return NextResponse.redirect(new URL('/login', req.url))
}

With no matcher, this runs on /login too. No token, redirect to /login, no token, redirect to /login, forever.

Fix 1: Exclude the Login Route and Static Assets

export function middleware(req: NextRequest) {
  const { pathname } = req.nextUrl
  const isPublic = pathname === '/login' || pathname.startsWith('/api/auth')
  const token = req.cookies.get('session')

  if (!token && !isPublic) {
    return NextResponse.redirect(new URL('/login', req.url))
  }
  if (token && pathname === '/login') {
    return NextResponse.redirect(new URL('/dashboard', req.url))
  }
  return NextResponse.next()
}

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico|.*\\.(?:png|jpg|svg|ico)$).*)'],
}

Always exclude _next/static and _next/image. Redirecting those requests breaks your CSS and JavaScript and can itself create loops.

The 5 Causes, in Order of Likelihood

# Cause How to spot it Fix
1 Middleware runs on its own redirect target Loop on /login or /onboarding Allow-list the target path
2 Cookie never sticks Network tab shows Set-Cookie but next request lacks it Match domain, secure, sameSite to the environment
3 Trailing slash conflict /about to /about/ and back Set trailingSlash once, remove manual redirects
4 Cloudflare SSL set to "Flexible" Origin redirects HTTP to HTTPS, Cloudflare keeps requesting HTTP Switch to "Full (strict)"
5 www and apex both redirect to each other Two redirect rules in the domain host and next.config Keep one canonical rule

Cause 2 is the sneaky one. A secure: true cookie is never stored over plain http://localhost, so auth works in production and loops locally, or the reverse when a proxy terminates TLS and your app thinks it is on HTTP.

Debug It in 60 Seconds

curl -sIL --max-redirs 6 https://yoursite.com/dashboard | grep -iE "^(HTTP|location)"

The repeating location: header shows the loop. Whichever two URLs alternate are your culprits.

Redirect Loops Are Invisible to Most Monitoring

Because the page never loads, client-side error tools see nothing, and your uptime check may still report 200 on the final hop. Our guide on knowing when your website is down covers synthetic checks that follow redirects and fail on a hop count. Middleware crashes are a separate failure mode; see Vercel Edge Runtime errors.

Catch It Before Users Do

Relia watches route-level outcomes and users' sessions. When a path starts returning only 307/308 responses, it writes the incident up in plain words: what happened, why it thinks so (with a confidence level), and one thing to do next. On request it writes a fix plan for the corrected matcher with a "Copy for your AI assistant" button; Relia doesn't change code itself. A deploy that locks everyone out gets caught by Relia instead of by a customer email.

FAQ

Why does my Next.js app redirect forever after adding middleware?

Middleware is running on the page it redirects to. Add a matcher or a path check so the destination is exempt.

Does NextResponse.redirect default to 307? Yes. It uses a temporary 307 unless you pass a status. Browsers cache 301 and 308 aggressively, so a bad permanent redirect can keep looping until the cache is cleared.

How do I clear a stuck 301 redirect loop?

Fix the server rule, then clear the browser cache or test in a private window. Permanent redirects are cached per browser.

All guides