next.js: Dynamic routes cause a "ChunkLoadError" when using the app router in a dockerized Next.js 13 SPA

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: linux
      Arch: x64
      Version: #85-Ubuntu SMP Fri Jul 7 15:25:09 UTC 2023
    Binaries:
      Node: 18.15.0
      npm: 9.5.0
      Yarn: N/A
      pnpm: N/A
    Relevant Packages:
      next: 13.4.15
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0
      typescript: N/A
    Next.js Config:
      output: N/A

Which area(s) of Next.js are affected? (leave empty if unsure)

App Router

Link to the code that reproduces this issue or a replay of the bug

https://github.com/eide-1/sample-project

To Reproduce

Steps to Reproduce:

  1. Run the the project in a production environment by following the instructions in the README file
  2. Click on the “Go to Dynamic Route” button. You will be presented with an application error
  3. Right-click anywhere on the webpage and click “Inspect”. The browser console will display the “ChunkLoadError”

Describe the Bug

I am currently working on upgrading an existing Next.js SPA that uses the pages router to the app router. The project is deployed using Docker and Nginx. However, I noticed that dynamic routes cause a “ChunkLoadError” when the SPA is deployed in a production environment. All pages (including dynamic routes) are functional in a development environment.

The dynamic route in question uses the “use client” directive. I noticed that if I remove the “use client” directive and any component or hook that requires it from the page, I can get it to render properly in production mode.

I created a sample project that uses the same tech stack as my current SPA to demonstrate the issue and I included the steps to reproduce the issue below.

I also found the following Stack Overflow question detailing a similar issue to the one I described above: In Next.js 13 using App Router, why can’t I export dynamic routes with “use client”?

Expected Behavior

Dynamic routes should work in the production environment just like they used to under the pages router without causing a ChunkLoadError.

Which browser are you using? (if relevant)

Microsoft Edge 115.0.1901.203 (64-bit)

How are you deploying your application? (if relevant)

Docker/Nginx

NEXT-1641

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 12
  • Comments: 66 (10 by maintainers)

Commits related to this issue

Most upvoted comments

Final message from me, apologies for triple posting. While this definitely is a regression in NextJS, I found the underlying root cause for my case: nginx was messing with the URL.

I use nginx to terminate TLS and reverse proxy the requests. When the proxy_pass rule ends with a slash, it gets rewritten. When it doesn’t end with a slash, the original request URL is passed through. (Obviously 🙄…)

I fixed it by changing my location rule from this:

location / {
	proxy_pass http://localhost:3001/;  # <-- ends with a slash
	proxy_set_header Host $host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

to the following, after which the latest NextJS canary works just fine:

location / {
	proxy_pass http://localhost:3001;  # <-- does not end with a slash
	proxy_set_header Host $host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Been tearing my hair out over this bug today 😭. Was introduced in v13.4.13-canary.0 by @ijjk in this PR https://github.com/vercel/next.js/pull/53029.

The problem is that when servers such as NGINX (& Apache) reverse proxy a request (using proxy_pass) they decode the URL before forwarding the request (StackOverflow). NextJS has always handled this, but it has been broken since v13.4.13-canary.0.

200 ✅ `/_next/static/chunks/pages/%5Bparent%5D/%5Bchild%5D-hash.js`
404 ❌ `/_next/static/chunks/pages/[parent]/[child]-hash.js` # URL transformed by NGINX

FWIW, this one-liner patch resolves the issue:

Screenshot 2023-09-25 at 23 09 29

cc. https://github.com/vercel/next.js/issues/54008#issuecomment-1712309065

I am seeing the same issue in our Docker Environments reverting to version 13.4.9 is a temporary fix for the issue.

Any urls with [] (%5B, %5D) return a 404 error which includes the generated js files for any dynamic page

This is fixed in latest patch release 13.5.4, please upgrade to the new version, thanks y’all for digging deep on this issue 🙏

I’ve confirmed that https://github.com/vercel/next.js/commit/1398de9977b89c9c4717d26e213b52bc63ccbe7e is the cause of the issue.

Looking at packages/next/src/server/lib/router-utils/filesystem.ts, the check on line 517 fails because curItemPath is not found in items (for type=nextStaticFolder). The state at this point is:

let curItemPath = "/_next/static/chunks/app/events/[slug]/page-8f8f16ccd387e59d.js";
let curDecodedItemPath = "/_next/static/chunks/app/events/[slug]/page-8f8f16ccd387e59d.js";
let items = [
    // ...
    "/_next/static/chunks/app/events/%5Bslug%5D/page-8f8f16ccd387e59d.js",
];

The entry in items was encoded on line 181:

// ensure filename is encoded
nextStaticFolderItems.add(
  path.posix.join('/_next/static', encodeURI(file))
)

If I remove the encodeURI call the app works properly and this issue is solved. I see that files in the public directory are similarly encoded on :147; I can reproduce this exact issue in that directory using a file called [hello].txt, which 404s in v13.4.13-canary.0, but works when I remove that encodeURI call too.

Hey @ijjk - I hope you don’t mind the mention - are you sure that the encodeURI calls are necessary here? Iow. could it be that the change you made to test/integration/i18n-support/test/shared.js hides an actual failure?

[edit] I also confirmed that the issue still exists in v13.4.20-canary.23, and that this commit in my fork fixes it. I haven’t yet been able to run the NextJS test suite to see if anything else breaks…

I develop and build on Docker env - so both npm run dev and npm run build are Dockerized all the time. Dockerized Linux (host = Ubuntu, guest/containers = debian).

I am seeing this issue on PROD builds (i.e. npm run build), starting v13.4.13 (works fine in v13.4.12). Testing every single release from v13.4.13 to v13.4.19 - all fail.

Dev env (again, Dockerized npm run dev) works just fine on the latest NextJs.

@janpaepke and others. I didn’t spend time on my AKS ingress config. Instead, I managed to get up and running with debugging nextjs and I’ve got a fix in a draft PR.

PR #56187

It will remain in draft until I get time to write a test to support this.

Hi everyone, we are looking into this!

The best way to help is to provide a minimal reproduction instead of “same issue”, etc. comments. It should be clear from your reproduction if you are using nginx, standalone (output: "standalone"), Docker, or a combination of these. You don’t need to comment “it’s still happening on x” as this information in itself is not helpful if we cannot see your code/config, instead provide a URL to a public reproduction. 🙏

Note: Please refrain from tagging maintainers for visibility, the issue is already tracked, so we are aware.

next.js 13.4.12 works fine Снимок экрана 2023-08-28 в 12 31 20

next.js 13.4.13 + broke my app Снимок экрана 2023-08-28 в 12 30 42

ive tested many versions and 13.4.12 is the last working one. As soon as I upgrade next to any version higher, dynamic routing breaks in interesting ways:

404 ChunkLoadError in a Docker Environment and just no content and no error for non docker deployments.

Super weird and very annoying. Also only on unix?

I am unable to reproduce this locally - with any version. Even latest works fine. But as soon as I deploy on a ubuntu cloud server -> router is broken again.

This affects both app and pages router.

For all followers of this: There’s movement in @omarmciver’s PR. Looks like this might be solved soon. 🥳

Guys this caused me a lot of head scratching. Thanks for this issue!

For the record (host OS: OSX):

  • local dev env (npm run dev) works
  • local build start (npm run build && npm start) works
  • local dockerized run (docker build, start container, forward port) WORKS!
  • deployed dockerized run - BREAKS

The most confusing part to me was that even running in docker worked for me locally. It lead me down a rabbit hole investigating if there are some weird ingress configurations on our cluster.

Whenever I deployed it, on the production version it would show:

“Application error: a client-side exception has occurred (see the browser console for more information).” In the console I could then see that all the js chunks that are in dynamic routes could not be loaded. I even checked in the docker container to confirm that the files are there (.next/static/chunks/app/[dynamicBit]).

It turned out to be this.

  • Downgrading to 13.4.12 fixed this
  • Upgrading to 13.4.20-canary.18 did NOT fix this.

Hope this saves someone some head-scratching.

I will investigate some more what might be going on here.

@omarmciver Thank you!

I just tested the last version v13.5.3-canary.4, unfortunately the same bug still exists. @balazsorban44 I’m assuming the label linear:next means you guys are looking at this, am I correct? Can we provide you with further information to support you in some way?

/edit and I can confirm that the bug also exists in v13.5.3.

As to Next’s standalone server: apparently it has its own URL rewrite issues, which have surfaced here. Nginx fix doesn’t fix it of course, but it fixes our use case, where Next server is replaced by Nginx. I hope I could explain my point.

@shehi yes but I’d like to focus on the actual issue which is an obvious regression.

There is also a problem with different letter case, “[slug]” works, but [slugCase] doesn’t.

@AmirL , the same as @poorscousertommy8 I have this issue even with all lowercase, [lang] to be specific. This is implementing i18n with the app router, roughly following the official example.

We have mentioned the issue to several maintainers now and it is clear we need their support. Let’s make it more likely that they will look into this issue by trying to limit additional comments to those which might shed further light on a potential solution.

changing the nginx config is not a fix - this is at max a hacky workaround

Current summary: This regression concerns all versions since v13.4.13-canary.0 @beverloo previously identified commit https://github.com/vercel/next.js/commit/1398de9977b89c9c4717d26e213b52bc63ccbe7e as the cause of the issue, which means it happened during this PR: https://github.com/vercel/next.js/pull/52492. Users running nginx can get around this issue by removing the trailing slash in their proxy_pass rule. However this issue remains unresolved for users using next start or the standalone server.

I’d love to offer my help but I’d need some insights from @ijjk, since the PR and commit mentioned above are quite extensive, so it’s hard to pinpoint the potential origin let alone appropriate solution.

I fixed it by changing my location rule from this:

location / {
	proxy_pass http://localhost:3001/;  # <-- ends with a slash
	proxy_set_header Host $host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

to the following, after which the latest NextJS canary works just fine:

location / {
	proxy_pass http://localhost:3001;  # <-- does not end with a slash
	proxy_set_header Host $host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Hey @beverloo, this seems to actually fix it for me, so weird. My stack is a self-hosted ubuntu 22.04, nginx, pm2, node 18.17.1, and now latest nextjs 13.4.19.

I tested on my Local (next build & next start) it works well. But I don’t know why on my server it not works.

i can confirm that this patch worked, i upgraded to 13.5.5 and all good again!

Still working on getting a test in place, then hopefully working my way to the top of the maintainers review list. Man, they have a lot of work!

@jlalmes thanks for your insights. Would you mind adding a pr for this?

Doesn’t work with update 13.5.1 either. If I start it locally (production build), then it works, it tries to load /_next/static/chunks/app/page-a599bfbc7c8a608a.js

If I use exactly the same build on the server (Windows), then it tries to load a completely different file (encoded): /_next/static/chunks/app/%5B…pagename%5D/page-8b669ad10c44488e.js which doesnt work. Why is that? I do not get it.

I’ve also been having this issue, and can reproduce Jan’s observation that this broke between v13.4.12 and v13.4.13-canary.0, which contains the following commits:

https://github.com/vercel/next.js/compare/v13.4.12...v13.4.13-canary.0

Another observation is the following: given a dynamic route parameter [slug],

  • “static/chunks/app/events/[slug]/layout-dd5472667df98622.js” exists on disk and is included in the build manifest,
  • “/_next/static/chunks/app/events/%5Bslug%5D/layout-dd5472667df98622.js” is requested by the browser, but 404s,
  • “/_next/static/chunks/app/events/%255Bslug%255D/layout-dd5472667df98622.js” works just fine.

Since the file exists on disk without any form of encoding, which also was the case in v13.4.12, that makes me think this likely is caused by a change in the included server.

This commit changes to how files are resolved, particularly the diffs in packages/next/src/server/lib/router-utils/. I see some encoding and decoding going on in there, but nothing stands out as the cause. There’s significant logic differences in filesystem.ts between dev and prod behaviour, and an interesting (but likely unrelated) clause in on :560-565 that seems to guard against this type of mismatch:

// In dev, we ensure encoded paths match
// decoded paths on the filesystem so check
// that variation as well
const tempItemPath = decodeURIComponent(curItemPath)
fsPath = path.posix.join(itemsRoot, tempItemPath)
found = await fileExists(fsPath, FileType.File)

I’m not really having any luck getting local changes to end up in the docker image, will try that again later…

I have more or less the same setup and the same issue (only dynamic routes), but I am only experiencing the error when I have Google Search Console “live test” my production URL, which makes this difficult to debug.

I’m not able to reproduce the error in production via Chrome Beta.

people please stop spamming, this is not a discussion but an issue, and I only want to get updates when there is progress, if it works for you just 👍the first message that says it started working or the issue got fixed.

For all users who use windows and iisnode, there is a solution https://github.com/vercel/next.js/issues/54325#issuecomment-1742153571.

@janpaepke and others. I didn’t spend time on my AKS ingress config. Instead, I managed to get up and running with debugging nextjs and I’ve got a fix in a draft PR.

PR #56187

It will remain in draft until I get time to write a test to support this.

Tysm for your efforts and contributions!!

Sorry Balázs for the tagging. I would love to provide a minimal reproduction, but I’m having a hard time with it because, similar to my colleagues who use nginx, the problem is probably between Next.js and my Windows Server (as already mentioned, I use iisnode) .

What I do is explained relatively simply: I run the setup according to the Next.js website (npx create-next-app@latest - incl. App Router) and create a folder in the app directory with a dynamic route ([…pagename ]). After deployment, loading the chunks fails.

@balazsorban44

Minified version of the problem here: https://github.com/omarmciver/ui-example-web

Spin it up with VSCode devcontainer extension. Include simple nginx config.

The README.md give instructions on how to recreate, and fix by not using client side rendering.

Using 13.5.3

@janpaepke There is also a problem with different letter case, “[slug]” works, but [slugCase] doesn’t.

my slug is […pagename] Unfortunately does not work.

Funny though, I have a deployment from 14 days ago (August 30th) which has next ^13.4.17 and that works fine. Going to play with other differences that might be affecting it.

My initial thought is webpack. We added webpack-merge since last time. Will update if I find anything.

UPDATE: My assumption was incorrect. Doesn’t work on that previous deployment. 😦 Downgraded to 13.4.12.

Same issue here. Use of Dynamic routes produce 404 with next start, but work fine in next dev. Downgrade to 13.4.12 works, 13.4.13+ (up to .19) breaks.

unfortunately this solution doesn’t really help me, as we don’t use nginx but use the standalone nextjs server.

Unfortunately the problem still exists in v13.4.20-canary.23. In production mode, the browser immediately throws a 404 error and the entire website crashes as soon as I access it. When I open the website locally in production mode, no error occurs. Only on a Windows IIS server with iisnode. It’s starting to get worrying for me, we recently switched to NextJS (at my will) and it seems like the problem isn’t going away 😦

13.4.12 is the last version that works without any problems.

@beverloo (sorry for mentioning) do you think the problem needs to be fixed by the Next.js team or do we also need to work on a server solution?

The structure of my app (with my dynamic route) is as follows: src -> app -> […pagename] -> page.tsx

same issue here I also hope that the Next.js team is working on it. We are currently stagnating on version 13.4.12 We don’t use Docker but on a Windows Server with IISNode

I have further narrowed down, that the breaking change must have been introduced in v13.4.13-canary.0 – it’s the first version where this occurs.

Looking at the changes, nothing stood out and unfortunately I lack the time for further analysis. Maybe this is a good starting point for someone, though.

Until then, we’ll (have to) stick with 13.4.12

ive tested many versions and 13.4.12 is the last working one. As soon as I upgrade next to any version higher, dynamic routing breaks in interesting ways.

404 ChunkLoadError in a Docker Environment and just no content and no error for non docker deployments. Super weird and very annoying. Also only on unix? I am unable to reproduce this locally - with any version. Even latest works fine. But as soon as I deploy on a ubuntu cloud server -> router is broken again.

This affects both app and pages router.

Yes, locally even the production version works fine for the latest version. The problem occurs only after deployment to a unix server.

@scottpaulin I realized that my issue is not limited to my dynamic routes. It affects a bunch of my pages. The Live Test fails about two thirds of the time. But I do think my pages are getting indexed as I can find them using Google Search and my production pages load just fine when I navigate to them in the browser. Perhaps it’s an issue with the Live Test crawler erroneously thinking that a certain chunk is unnecessary and not loading it. I’m hoping it’s not actually impacting SEO…

Anyone can check this??? 😦( I can not use newest version…

I am seeing the same issue in our Docker Environments reverting to version 13.4.9 is a temporary fix for the issue.

Any urls with [] (%5B, %5D) return a 404 error which includes the generated js files for any dynamic page

I can confirm this solution works. The issue begins occurring since version 13.4.13-canary.16.