# Fix next-intl middleware locale detection redirect loop

## TL;DR

The middleware keeps redirecting because the locale it detects never sticks, so stop the loop by excluding the redirect target from detection. Usually the matcher re-runs on the already-prefixed URL, or the cookie and the Accept-Language header disagree forever. Make detection idempotent: if the URL already has a valid prefix, do nothing.

## The error

```text
ERR_TOO_MANY_REDIRECTS on YOUR_HOST/
/ to /en to /en to /en ... (network tab shows the same redirect repeating)
```

## Fix it

### Step 1: Watch the redirect chain to see the loop

```bash
curl -s -o /dev/null -w "%{redirect_url}" YOUR_HOST/ | head -c 200
```

Expected: You see the URL redirecting to itself or bouncing between two URLs.

### Step 2: Check the middleware matcher for self-matching

```bash
grep -n "matcher" -A 3 src/middleware.js
```

Expected: The matcher must not re-trigger on URLs that already carry a locale prefix.

### Step 3: Make detection skip already-prefixed paths

```bash
node -e "console.log('pattern: if the pathname starts with a known locale, return NextResponse.next() with no redirect')"
```

Expected: One request, one redirect at most, then the prefixed page serves.

### Step 4: Clear the locale cookie and retry

```bash
curl -s -c /tmp/cj -b /tmp/cj -o /dev/null -w "%{http_code} %{redirect_url}" YOUR_HOST/
```

Expected: You get a single 307 to /en and then a 200.

## When to use this

- The browser reports too many redirects on a next-intl site
- The network tab shows / bouncing to /en repeatedly

## When NOT to use this

- A single redirect to the wrong locale, that is a detection config issue not a loop
- Redirects involving auth pages, check your auth middleware order

## Tool and version compatibility

- next-intl v3/v4 middleware, Next.js 12/13/14
- Locale detection via Accept-Language header, cookie, or both

## Variant phrasings

### loop between /en and /en-US

Your locales list has both but detection canonicalizes differently than the prefix. Pick one form and stick to it.

### loop only for logged-in users

Something sets the locale cookie after the middleware runs. Set it before, or let the middleware own it.

## Why it happens

The middleware redirects to add the locale prefix, but on the next request it runs again and redirects again, because the already-prefixed URL still looks undetected to it, or the cookie it sets gets overwritten. Each pass looks like a fresh visitor, so it never stops.

## Edge cases

- Multiple middleware in a chain can each redirect, merge them into one response
- Domain-based routing plus prefix routing double up, use one strategy
- Bots without Accept-Language can loop forever, give them the default locale with no redirect

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_emoBG81uYRSnQ6uy8QAvfg
