500 Internal Server Error On Dynamic Routes With %25 When CacheComponents Enabled
When cacheComponents is enabled in Next.js 16.1.0-canary.16, dynamic routes that receive an already decoded percent sign (%) from a URL-encoded %25 trigger a 500 Internal Server Error due to invalid URI decoding during cache key generation.
The cacheComponents cache key generation double-decodes dynamic route parameters. The request path /%25 is decoded to /% by Next.js before params are passed to the page. cacheComponents then calls decodeURIComponent on the already-decoded param value '%', which throws URIError: URI malformed because '%' is not followed by two hex digits. Other encoded characters (e.g. %24 -> $) decode to characters that are valid when passed to decodeURIComponent again, so they do not throw.
1. Enable cacheComponents in next.config.ts
2. Create a dynamic route (e.g. pages/[slug].tsx)
3. Build and start the app: npm run build && npm run start
4. Navigate to http://localhost:3000/%25
5. Observe the 500 Internal Server Error
This monkey patch overrides the global decodeURIComponent to catch URIError and return the original string unchanged. Because the dynamic param value is already decoded by Next.js before reaching cacheComponents, the double decode fails only for the bare '%' character. Returning the original value avoids the exception and allows the page to render correctly. This is a temporary workaround; the proper fix is to remove the erroneous decodeURIComponent call from cacheComponents.
Edge Case Audit
This patch overrides the global decodeURIComponent, which may mask legitimate URI decoding errors in other parts of the application or dependencies. It can cause unexpected behavior if any code relies on decodeURIComponent to throw for malformed input. Use only as a temporary hotfix until the underlying issue is fixed upstream. Rollback: remove the patch and set cacheComponents: false if the error persists.