Link to the code that reproduces this issue
https://github.com/y-pakorn/next-malformed-param-500
To Reproduce
- Clone the reproduction, then run
npm install, npm run build and npm start.
- Request the dynamic route with a malformed percent-encoded segment:
curl -o /dev/null -w '%{http_code}\n' http://localhost:3000/items/%E0%A4
curl -o /dev/null -w '%{http_code}\n' http://localhost:3000/items/100%
The app has one dynamic route, app/items/[slug]/page.tsx, and no pages directory.
Current vs. Expected behavior
Both requests return 500 Internal Server Error with a plain text body, and nothing is logged.
I expected 400 Bad Request. next dev returns 400 for the same URLs, and so does next start once the project has any Pages Router route. A valid slug such as /items/hello returns 200, and a malformed static path such as /%E0%A4 returns 404, so only dynamic segments are affected.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.5.0: Mon Apr 27 20:41:12 PDT 2026; root:xnu-12377.121.6~2/RELEASE_ARM64_T6050
Available memory (MB): 24576
Available CPU cores: 15
Binaries:
Node: 26.3.0
npm: 11.16.0
Yarn: N/A
pnpm: 12.4.1
Relevant Packages:
next: 16.4.0-canary.51 // Latest available version is detected (16.4.0-canary.51).
eslint-config-next: N/A
react: 19.3.0
react-dom: 19.3.0
typescript: 7.0.2
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Dynamic Routes, Error Handling
Which stage(s) are affected? (Select all that apply)
next start (local), Other (Deployed)
Additional context
This also reproduces on 16.3.6 and 16.3.5. We hit it in production on a self-hosted output: "standalone" deployment running 16.3.5.
For these URLs, getRouteMatcher throws DecodeError('failed to decode param'), error code E528. base-server catches DecodeError and renders /_error with status 400, and router-server maps it to a 400 as well. An App Router-only build has no _error page, though. Its .next/server/pages directory contains only 404.html and 500.html. After adding one Pages Router route, the build includes _error.js and the same requests return 400. My guess is that the 400 response depends on the Pages Router error page and ends in a bare 500 when the build doesn't include one.
This looks like a regression of #43303. The test added for that issue in test/integration/dynamic-routing only covers the Pages Router.
Link to the code that reproduces this issue
https://github.com/y-pakorn/next-malformed-param-500
To Reproduce
npm install,npm run buildandnpm start.The app has one dynamic route,
app/items/[slug]/page.tsx, and nopagesdirectory.Current vs. Expected behavior
Both requests return
500 Internal Server Errorwith a plain text body, and nothing is logged.I expected
400 Bad Request.next devreturns 400 for the same URLs, and so doesnext startonce the project has any Pages Router route. A valid slug such as/items/helloreturns 200, and a malformed static path such as/%E0%A4returns 404, so only dynamic segments are affected.Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 25.5.0: Mon Apr 27 20:41:12 PDT 2026; root:xnu-12377.121.6~2/RELEASE_ARM64_T6050 Available memory (MB): 24576 Available CPU cores: 15 Binaries: Node: 26.3.0 npm: 11.16.0 Yarn: N/A pnpm: 12.4.1 Relevant Packages: next: 16.4.0-canary.51 // Latest available version is detected (16.4.0-canary.51). eslint-config-next: N/A react: 19.3.0 react-dom: 19.3.0 typescript: 7.0.2 Next.js Config: output: N/AWhich area(s) are affected? (Select all that apply)
Dynamic Routes, Error Handling
Which stage(s) are affected? (Select all that apply)
next start (local), Other (Deployed)
Additional context
This also reproduces on 16.3.6 and 16.3.5. We hit it in production on a self-hosted
output: "standalone"deployment running 16.3.5.For these URLs,
getRouteMatcherthrowsDecodeError('failed to decode param'), error code E528.base-servercatchesDecodeErrorand renders/_errorwith status 400, androuter-servermaps it to a 400 as well. An App Router-only build has no_errorpage, though. Its.next/server/pagesdirectory contains only404.htmland500.html. After adding one Pages Router route, the build includes_error.jsand the same requests return 400. My guess is that the 400 response depends on the Pages Router error page and ends in a bare 500 when the build doesn't include one.This looks like a regression of #43303. The test added for that issue in
test/integration/dynamic-routingonly covers the Pages Router.