nextjs - 💡(How to fix) Fix Standalone server 307-redirect-loops on next-intl localePrefix rewrites since 16.2.6 (rewrite emitted as absolute localhost URL)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Code Example

PORT=8080 HOSTNAME=0.0.0.0 node .next/standalone/server.js
   curl -sS -D - -o /dev/null http://127.0.0.1:8080/login

---

HTTP/1.1 200 OK
x-middleware-rewrite: /en/login        ← relative, resolved internally

---

HTTP/1.1 307 Temporary Redirect
x-middleware-rewrite: http://localhost:8080/en/login   ← absolute
location: /login

---

const initUrl = `${protocol}://${formatHostname(opts.hostname || 'localhost')}:${port}${req.url}`
// getRelativeURL(rewrite, initUrl) only strips the origin if origins match
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

Minimal: App Router + [email protected] with localePrefix: "as-needed", output: "standalone".

To Reproduce

  1. App Router app using next-intl middleware (proxy.ts/middleware.ts) with localePrefix: "as-needed" and default locale en.
  2. next build with output: "standalone".
  3. Run the standalone server bound to a non-localhost host (the standalone default):
    PORT=8080 HOSTNAME=0.0.0.0 node .next/standalone/server.js
    curl -sS -D - -o /dev/null http://127.0.0.1:8080/login

Current vs. Expected behavior

Expected (and the behavior on 16.2.5): a default-locale path is rewritten internally and served 200:

HTTP/1.1 200 OK
x-middleware-rewrite: /en/login        ← relative, resolved internally

Actual (16.2.6 and 16.2.7): the rewrite is emitted as an absolute localhost URL and surfaced to the client as a 307 redirect to the original path → infinite loop (ERR_TOO_MANY_REDIRECTS):

HTTP/1.1 307 Temporary Redirect
x-middleware-rewrite: http://localhost:8080/en/login   ← absolute
location: /login

Bisect

  • 16.2.5 → works (relative rewrite, 200)
  • 16.2.6 → broken (absolute rewrite, 307 loop)
  • 16.2.7 → broken

next dev is not affected (it emits a relative rewrite). Only the standalone production server loops.

Analysis (what we found)

The proxy worker emits the next-intl rewrite as an absolute URL whose host is localhost. In server/lib/router-utils/resolve-routes.js, the rewrite is relativized against an initUrl built from the server bind hostname:

const initUrl = `${protocol}://${formatHostname(opts.hostname || 'localhost')}:${port}${req.url}`
// getRelativeURL(rewrite, initUrl) only strips the origin if origins match

With the standalone default HOSTNAME=0.0.0.0, initUrl host is 0.0.0.0 while the rewrite host is localhost, so on 16.2.6 the rewrite is treated as a cross-origin (external) rewrite and leaked as a 307 to the original path. On 16.2.5 the same setup resolved internally.

This looks like a side-effect of the proxy/middleware-rewrite hardening that shipped in the 16.2.6 security release. We'd appreciate guidance on the intended way to keep an i18n rewrite internal under the standalone Node-runtime proxy when the bind host isn't localhost (e.g. behind a reverse proxy / in a container binding 0.0.0.0).

Provide environment information

  • next: 16.2.6 / 16.2.7 (regression from 16.2.5)
  • next-intl: 4.12.0
  • Deployment: output: "standalone", node server.js, Node 20, Linux/Docker

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING