DEV Community

Cover image for Fixing a Weird Next.js Chunk Loading Issue Caused by Load Balancer URL Normalization
alfanfauzy
alfanfauzy

Posted on

Fixing a Weird Next.js Chunk Loading Issue Caused by Load Balancer URL Normalization

When Everything Works in Office, but Breaks in Client’s Server

Recently I faced an interesting bug when deploying a Next.js project.
On our office server, everything worked perfectly. But when the same Docker image was deployed in our client’s environment, the app broke — static chunks could not be loaded.


The Symptom

My app uses a dynamic route like:

   app/feature/[work_id]/listing/page.tsx

Enter fullscreen mode Exit fullscreen mode

So Next.js generates static chunks with an encoded path like:

   /_next/static/chunks/app/feature/%5Bwork_id%5D/listing/page-xxxxx.js

Enter fullscreen mode Exit fullscreen mode

But in the client’s server, I noticed requests were being made to:

   /_next/static/chunks/app/feature/%5bwork_id%5d/listing/page-xxxxx.js

Enter fullscreen mode Exit fullscreen mode

Spot the difference? %5B vs %5b.
Both are technically valid encodings of [ but they are not the same string.


Why Did This Happen?

It turned out to be related to their load balancer.

  • URL encoding is case-insensitive (%5B = %5b = [).
  • But depending on the load balancer/proxy settings, hex characters can be normalized into lowercase.

In my office environment, the load balancer kept it uppercase.
In the client environment, it forced lowercase.


The Impact

Next.js expected chunks at %5Bwork_id%5D, but the request came in as %5bwork_id%5d.
Result: the chunk was not found, and the page broke.


The Fix

I added a simple middleware in Next.js to normalize the path:

   if (url.pathname.includes('%5b') || url.pathname.includes('%5d')) {
    const normalizedPath = url.pathname
      .replace(/%5b/g, '%5B')
      .replace(/%5d/g, '%5D');

    url.pathname = normalizedPath;

    return NextResponse.rewrite(url);
  }

Enter fullscreen mode Exit fullscreen mode

This way, any lowercase %5b or %5d is rewritten back to uppercase, and Next.js can resolve the chunks.


🛠 Debug with cURL

After fixing the encoding in middleware (replacing %5b → %5B and %5d → %5D), I try to verify whether the chunk is correctly served.

   curl -v http://localhost:5000/_next/static/chunks/app/feature/%5bworkd_id%5d/listing/%5bdocument_id%5d/extraction/page-638a1fa4c352c07e.js

Enter fullscreen mode Exit fullscreen mode
  • -v → verbose mode, shows both headers and body.

  • If the fix is correct, will should see a 200 OK response with headers like:

   HTTP/1.1 200 OK
   Content-Type: application/javascript; charset=utf-8
   Cache-Control: public, max-age=31536000, immutable
Enter fullscreen mode Exit fullscreen mode

…and the body will be minified JavaScript.

  • If the response is 404 Not Found, the chunk is still not being resolved correctly (likely an encoding issue remains).

Lessons Learned

  • Bugs are not always in your code — infra can surprise you.
  • URL encoding might look trivial, but consistency matters when loading static chunks.
  • Next.js middleware can be a lifesaver for defensive fixes like this.

Have you ever faced a similar environment-only bug? I’d love to hear your story.

Top comments (0)