Skip to content

fix(control-plane): pin next to 16.2.5 to fix standalone i18n redirect loop (#1926)#1928

Merged
nicoloboschi merged 1 commit into
mainfrom
fix/cp-pin-next-16-2-5
Jun 2, 2026
Merged

fix(control-plane): pin next to 16.2.5 to fix standalone i18n redirect loop (#1926)#1928
nicoloboschi merged 1 commit into
mainfrom
fix/cp-pin-next-16-2-5

Conversation

@nicoloboschi
Copy link
Copy Markdown
Collaborator

Summary

Fixes #1926 — every control-plane page route 307-redirect-loops (ERR_TOO_MANY_REDIRECTS) under the standalone production server.

Root cause: a Next.js regression in 16.2.6. With the standalone default HOSTNAME=0.0.0.0, next-intl's localePrefix: "as-needed" locale rewrite is emitted as an absolute localhost URL and resolved as cross-origin, so the rewrite leaks to the client as a 307 to the original path → loop.

Bisected (raw standalone, HOSTNAME=0.0.0.0, identical CP code):

next i18n page routes
16.1.7 ✅ 200 (relative rewrite)
16.2.5 ✅ 200 (relative rewrite)
16.2.6 ❌ 307 loop (absolute rewrite)
16.2.7 ❌ 307 loop

next dev is not affected — only the standalone build, which is why it surfaced only when building/shipping the production image. This is also why 0.7.1 images that resolved 16.2.5 worked.

Change

  • Pin next to 16.2.5 (exact) in hindsight-control-plane.
  • Add a root overrides.next: "16.2.5" so next-intl's peer dedupes to the same single version (a 16.2.5/16.2.6 split fails the CP typecheck with a NextRequest mismatch).
  • Lockfile updated minimally (next-family 16.2.6 → 16.2.5, single hoisted, all platform binaries preserved).

⚠️ Temporary pin

16.2.6 is a security release (multiple high-severity middleware/proxy bypass fixes + an SSRF). Pinning to 16.2.5 re-opens those, so this should be treated as a stopgap until the regression is fixed upstream and we can move back to a patched version.

Upstream issue filed for guidance: vercel/next.js#94342

Verification

  • npm ci at root → single deduped next@16.2.5, consistent lockfile.
  • npm run build --workspace=hindsight-control-plane → compiles + typechecks.
  • Standalone HOSTNAME=0.0.0.0: /login, /banks/abc, /es/login200 (was 307 loop).

Note: the issue's manual repro uses HOSTNAME=127.0.0.1, which is a stricter case that still loops on 16.2.5 — but it is not a deployment path (all launchers default to 0.0.0.0). Verify with HOSTNAME=0.0.0.0.

…t loop (#1926)

next 16.2.6 regressed how the standalone server resolves next-intl locale
rewrites. With the standalone default HOSTNAME=0.0.0.0, the i18n rewrite is
emitted as an absolute localhost URL and treated as cross-origin, so every page
route returns a 307 to itself (ERR_TOO_MANY_REDIRECTS). Bisected: 16.2.5 serves
200 with a relative rewrite; 16.2.6 and 16.2.7 loop. next dev is unaffected.

Pin next to 16.2.5 (exact) and add a root override so next-intl's peer dedupes
to the same single version — a 16.2.5/16.2.6 split fails the control-plane
typecheck. The Docker image build resolves the exact pin; CI `npm ci` installs
the pinned lockfile (single hoisted next@16.2.5, all platform binaries kept).

Temporary: 16.2.6 is a security release, so we should return to a patched
version once the regression is fixed upstream. Tracking: vercel/next.js#94342.
@nicoloboschi nicoloboschi merged commit 201f5d7 into main Jun 2, 2026
196 of 207 checks passed
nicoloboschi added a commit that referenced this pull request Jun 2, 2026
)

Reverts the temporary `next` pin from #1928. Deeper investigation showed the
control-plane redirect loop (#1926) is NOT a 16.2.6 regression: it reproduces
identically on 16.2.5 and 16.2.6, and is triggered specifically by binding the
standalone server to HOSTNAME=127.0.0.1 (Next normalizes 127.0.0.1 -> localhost
in the proxy request URL but keeps 127.0.0.1 in the router's initUrl, so the
next-intl locale rewrite looks cross-origin and leaks as a 307 loop).

The production launchers (docker start-all.sh, bin/cli.js) bind HOSTNAME=0.0.0.0,
which serves 200 on every version, so the pin neither fixed #1926's repro nor was
needed for production. Restoring ^16.2.6 brings back the 16.2.6 security fixes
(proxy-bypass + SSRF). The 127.0.0.1-binding quirk is unrelated to the version.

Verified: npm ci -> single next@16.2.7; control-plane build typechecks; standalone
on HOSTNAME=0.0.0.0 serves /login, /banks/*, /es/login as 200.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Control plane: every page route 307-redirect-loops under Next 16 (next-intl rewrite leaked as redirect)

1 participant