cloudflare/vinext

Middleware rewrite target route resolution uses wrong priority

Closed

#1,331 opened on May 20, 2026

 (1 comment) (0 reactions) (0 assignees)TypeScript (371 forks)github user discovery
adapter-api-e2ehelp wanted

Repository metrics

Stars
 (8,563 stars)
PR merge metrics
 (Avg merge 1d 1h) (462 merged PRs in 30d)

Description

This issue was created by an agent analysing CI failures from the Next.js Deploy Suite (vinext main vs Next.js v16.2.6, 2026-05-20).

Problem

After middleware rewrites a request URL, the rewritten path is matched against the route table with incorrect priority. Dynamic catch-all routes ([id]/[slug]) capture the rewrite target instead of resolving to the correct static or named page.

For example, when middleware rewrites /rewrite-1 to /:

  • Expected: The home page renders ("Hello World")
  • Actual: The [id] dynamic route captures it, rendering "Dynamic route" with query.id = "rewrite-1"
Expected substring: "Hello World"
Received string:    "...<p class=\"title\">Dynamic route</p>..."

This also affects:

  • Rewrites to named pages like /about (renders [id] instead)
  • External rewrites (to example.com) resulting in 404 instead of proxying
  • fallback: true pages rendering full data immediately instead of the fallback/loading state

Estimated Impact

~35 test failures across the deploy suite.

Affected Test Suites

  • test/e2e/middleware-trailing-slash/test/index.test.ts (~10 failures)
  • test/e2e/middleware-rewrites/test/index.test.ts (~12 failures)
  • test/e2e/basepath/redirect-and-rewrite.test.ts
  • test/e2e/app-dir/app-middleware-proxy/app-middleware-proxy.test.ts

Recommendation

  1. Reproduce first in vinext's own test suite. Add a test case with a middleware that rewrites to a known static page and a dynamic [id] route. Assert the static page renders, not the dynamic route. Confirm it fails.

  2. Study Next.js route matching after rewrites. In Next.js, after a middleware rewrite, the rewritten URL is re-matched against the full route table with proper priority: static routes > predefined dynamic routes > catch-all routes. Search .nextjs-ref/packages/next/src/server/ for how post-rewrite matching works.

  3. Fix the post-rewrite route matcher. The rewritten path should go through the full filesystem route resolution, not just dynamic route matching. Static routes and named pages must take priority over dynamic catch-alls.

  4. Implement external URL proxying for rewrites. When middleware rewrites to an absolute external URL (e.g., https://example.com), the server should proxy the request to that URL and return the response, rather than matching it against local routes.

  5. Check dev/prod parity. Ensure the fix applies to both server/dev-server.ts and server/prod-server.ts.

Contributor guide