Your Next.js middleware redirects to /login, but /login also triggers the middleware, which redirects to /login again. Infinite loop. The browser shows βERR_TOO_MANY_REDIRECTS.β
What causes this error
- Middleware runs on the redirect target β your matcher catches
/logintoo - Missing pathname check β you redirect all unauthenticated requests without excluding public pages
- Cookie not being set β the auth cookie isnβt persisted, so every request looks unauthenticated
Fix 1: Exclude public routes from the matcher
// middleware.ts
export const config = {
matcher: [
// Match all paths EXCEPT static files, api routes, and public pages
'/((?!api|_next/static|_next/image|favicon.ico|login|signup|public).*)',
],
};
Fix 2: Check the pathname inside middleware
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
const publicPaths = ['/login', '/signup', '/forgot-password', '/'];
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Don't redirect if already on a public page
if (publicPaths.some(path => pathname.startsWith(path))) {
return NextResponse.next();
}
const token = request.cookies.get('auth-token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
Fix 3: Check for redirect loops explicitly
// Prevent redirect loops by checking the referer
const referer = request.headers.get('referer');
if (referer?.includes('/login')) {
return NextResponse.next(); // Don't redirect again
}
How to debug
Add logging to your middleware to see whatβs happening:
export function middleware(request: NextRequest) {
console.log('Middleware:', request.nextUrl.pathname);
// ... rest of middleware
}
Check the terminal (not browser console) β middleware runs on the server.
Related: Next.js cheat sheet Β· Next.js Hydration Error fix Β· Next.js vs Astro Β· What is Next.js