nextjs - ✅(Solved) Fix Turbopack 16.2.0 generates filenames with reserved characters (~~, ...) breaking Enterprise WAF/Nginx rules [1 pull requests, 2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#91678Fetched 2026-04-08 01:02:31
View on GitHub
Comments
2
Participants
3
Timeline
11
Reactions
3
Author
Timeline (top)
referenced ×3commented ×2subscribed ×2closed ×1

Fix Action

Fixed

PR fix notes

PR #91832: Turbopack: switch from base40 to base38 hash encoding (remove ~ and . from charset)

Description (problem / solution / changelog)

What?

Switch Turbopack's hash encoding charset from base40 (0-9 a-z _ - ~ .) to base38 (0-9 a-z _ -), removing the ~ and . characters. Pure rename/charset change — no structural changes.

Why?

The ~ and . characters in base40-encoded filenames are blocked by standard Nginx hardening rules (block_common_exploits.conf) and enterprise WAF configurations, causing 403 Forbidden errors when applications are deployed behind security-hardened infrastructure.

Examples of problematic filenames:

  • turbopack-0c3o1svijj_~~.js~~ flagged as directory traversal / injection
  • 0...f7~att2_2.js... flagged as path traversal attempt
  • 0q~2copru0zy0.css~ filtered by some WAF rulesets

Previous hex-only filenames (e.g. turbopack-01ca012029ca2e66.js) had no such issues.

Fixes https://github.com/vercel/next.js/issues/91678

How?

Charset change (turbo-tasks-hash/src/base38.rs, renamed from base40.rs):

  • Alphabet reduced from 40 to 38 characters: 0123456789abcdefghijklmnopqrstuvwxyz_-
  • All constants and functions renamed: BASE40_*BASE38_*, encode_base40encode_base38
  • Hash lengths unchanged: 13 chars for 64-bit, 25 chars for 128-bit (38^13 > 2^64, 38^25 > 2^128)
  • Content hash length stays at 13 (68.2 bits vs 69.2 bits with base40 — negligible)

HashAlgorithm enum variants (turbo-tasks-hash/src/lib.rs):

  • Xxh3Hash64Base40Xxh3Hash64Base38
  • Xxh3Hash128Base40Xxh3Hash128Base38

Bit computation comment (turbopack-core/src/ident.rs):

  • Updated 7 base38 chars ≈ 37 bits≈ 36 bits (log2(38) × 7 = 36.7)

Test regex patterns (15 test files):

  • Updated [0-9a-z_.~-][0-9a-z_-] to match the new charset

Changed files

  • test/e2e/app-dir-export/test/utils.ts (modified, +4/-12)
  • test/e2e/app-dir/app/index.test.ts (modified, +1/-1)
  • test/e2e/app-dir/next-image/next-image-proxy.test.ts (modified, +1/-1)
  • test/e2e/app-dir/next-image/next-image.test.ts (modified, +1/-1)
  • test/e2e/app-dir/node-worker-threads/node-worker-threads.test.ts (modified, +1/-1)
  • test/e2e/app-dir/webpack-loader-module-type/webpack-loader-module-type.test.ts (modified, +1/-1)
  • test/e2e/edge-compiler-can-import-blob-assets/index.test.ts (modified, +3/-3)
  • test/e2e/url-imports/url-imports.test.ts (modified, +3/-3)
  • test/e2e/url/url.test.ts (modified, +1/-1)
  • test/integration/css/test/basic-global-support.test.ts (modified, +9/-9)
  • test/integration/image-optimizer/test/util.ts (modified, +1/-1)
  • test/integration/next-image-legacy/unoptimized/test/index.test.ts (modified, +1/-1)
  • test/integration/next-image-new/app-dir/test/index.test.ts (modified, +1/-1)
  • test/integration/next-image-new/both-basepath-trailingslash/test/index.test.ts (modified, +1/-1)
  • test/integration/next-image-new/default/test/index.test.ts (modified, +1/-1)
  • turbopack/crates/turbo-tasks-hash/src/base38.rs (renamed, +27/-22)
  • turbopack/crates/turbo-tasks-hash/src/lib.rs (modified, +11/-11)
  • turbopack/crates/turbopack-browser/src/chunking_context.rs (modified, +1/-1)
  • turbopack/crates/turbopack-core/src/chunk/mod.rs (modified, +1/-1)
  • turbopack/crates/turbopack-core/src/ident.rs (modified, +5/-5)
  • turbopack/crates/turbopack-core/src/version.rs (modified, +1/-1)
  • turbopack/crates/turbopack-static/src/output_asset.rs (modified, +1/-1)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/dynamic-import/output/0tuk_tests_snapshot_basic-tree-shake_dynamic-import_input_index_0q~hmwn.js (removed, +0/-5)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/dynamic-import/output/1ece_tests_snapshot_basic-tree-shake_dynamic-import_input_index_0qno3y-.js (added, +5/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/dynamic-import/output/1jsg_tests_snapshot_basic-tree-shake_dynamic-import_input_index_0qno3y-.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/dynamic-import/output/1jsg_tests_snapshot_basic-tree-shake_dynamic-import_input_index_17se2p5.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/dynamic-import/output/1jsg_tests_snapshot_basic-tree-shake_dynamic-import_input_index_17se2p5.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/dynamic-import/output/1jsg_tests_snapshot_basic-tree-shake_dynamic-import_input_lib_1b34ju5.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/dynamic-import/output/1jsg_tests_snapshot_basic-tree-shake_dynamic-import_input_lib_1b34ju5.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/dynamic-import/output/1jsg_tests_snapshot_basic-tree-shake_dynamic-import_input_lib_1y039z7.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/dynamic-import/output/1jsg_tests_snapshot_basic-tree-shake_dynamic-import_input_lib_1y039z7.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/export-named/output/0_9x_turbopack-tests_tests_snapshot_basic-tree-shake_export-named_input_0xj7csh._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/export-named/output/0_9x_turbopack-tests_tests_snapshot_basic-tree-shake_export-named_input_0xj7csh._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/export-named/output/1ece_tests_snapshot_basic-tree-shake_export-named_input_index_210e6bp.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/export-named/output/1jsg_tests_snapshot_basic-tree-shake_export-named_input_index_210e6bp.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/export-namespace/output/0_9x_turbopack-tests_tests_snapshot_basic-tree-shake_export-namespace_input_1mqgz2-._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/export-namespace/output/0_9x_turbopack-tests_tests_snapshot_basic-tree-shake_export-namespace_input_1mqgz2-._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/export-namespace/output/1ece_tests_snapshot_basic-tree-shake_export-namespace_input_index_0tbr8qy.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/export-namespace/output/1jsg_tests_snapshot_basic-tree-shake_export-namespace_input_index_0tbr8qy.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-named-all/output/0_9x_turbopack-tests_tests_snapshot_basic-tree-shake_import-named-all_input_1orhvu2._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-named-all/output/0_9x_turbopack-tests_tests_snapshot_basic-tree-shake_import-named-all_input_1orhvu2._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-named-all/output/1ece_tests_snapshot_basic-tree-shake_import-named-all_input_index_0ol2hm0.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-named-all/output/1jsg_tests_snapshot_basic-tree-shake_import-named-all_input_index_0ol2hm0.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-named/output/0_9x_turbopack-tests_tests_snapshot_basic-tree-shake_import-named_input_1j9uhcy._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-named/output/0_9x_turbopack-tests_tests_snapshot_basic-tree-shake_import-named_input_1j9uhcy._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-named/output/1ece_tests_snapshot_basic-tree-shake_import-named_input_index_1c8nbdp.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-named/output/1jsg_tests_snapshot_basic-tree-shake_import-named_input_index_1c8nbdp.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-namespace/output/0_9x_turbopack-tests_tests_snapshot_basic-tree-shake_import-namespace_input_1ippwh3._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-namespace/output/0_9x_turbopack-tests_tests_snapshot_basic-tree-shake_import-namespace_input_1ippwh3._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-namespace/output/1ece_tests_snapshot_basic-tree-shake_import-namespace_input_index_0-n2_vs.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-namespace/output/1jsg_tests_snapshot_basic-tree-shake_import-namespace_input_index_0-n2_vs.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-side-effect/output/0tuk_tests_snapshot_basic-tree-shake_import-side-effect_input_index_05zmix2.js (removed, +0/-5)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-side-effect/output/1ece_tests_snapshot_basic-tree-shake_import-side-effect_input_index_0g7y89f.js (added, +5/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-side-effect/output/1jsg_tests_snapshot_basic-tree-shake_import-side-effect_input_1_hdh9i._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-side-effect/output/1jsg_tests_snapshot_basic-tree-shake_import-side-effect_input_1_hdh9i._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/import-side-effect/output/1jsg_tests_snapshot_basic-tree-shake_import-side-effect_input_index_0g7y89f.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/require-side-effect/output/0tuk_tests_snapshot_basic-tree-shake_require-side-effect_input_index_0v7fuxm.js (removed, +0/-5)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/require-side-effect/output/1ece_tests_snapshot_basic-tree-shake_require-side-effect_input_index_1183joi.js (added, +5/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/require-side-effect/output/1jsg_tests_snapshot_basic-tree-shake_require-side-effect_input_0fs4qhn._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/require-side-effect/output/1jsg_tests_snapshot_basic-tree-shake_require-side-effect_input_0fs4qhn._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/require-side-effect/output/1jsg_tests_snapshot_basic-tree-shake_require-side-effect_input_index_1183joi.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/tree-shake-test-1/output/0tuk_tests_snapshot_basic-tree-shake_tree-shake-test-1_input_index_0dmw76_.js (removed, +0/-5)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/tree-shake-test-1/output/1ece_tests_snapshot_basic-tree-shake_tree-shake-test-1_input_index_0z2elrc.js (added, +5/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/tree-shake-test-1/output/1jsg_tests_snapshot_basic-tree-shake_tree-shake-test-1_input_index_07jttq5.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/tree-shake-test-1/output/1jsg_tests_snapshot_basic-tree-shake_tree-shake-test-1_input_index_07jttq5.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic-tree-shake/tree-shake-test-1/output/1jsg_tests_snapshot_basic-tree-shake_tree-shake-test-1_input_index_0z2elrc.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/0v.~_crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_03rd2w8.js (removed, +0/-5)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/1do3_crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_1ka8r7j.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/1do3_crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_import_1ka8r7j.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/1do3_crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_0k4s9ge.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/1i9t_crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_index_0k4s9ge.js (added, +5/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/turbopack_crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_1lkohl-._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/turbopack_crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_1lkohl-._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/turbopack_crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_1tjv7of._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk/output/turbopack_crates_turbopack-tests_tests_snapshot_basic_async_chunk_input_1tjv7of._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk_build/output/1do3_crates_turbopack-tests_tests_snapshot_basic_async_chunk_build_input_0aldyki._.js (renamed, +1/-1)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk_build/output/1do3_crates_turbopack-tests_tests_snapshot_basic_async_chunk_build_input_0aldyki._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk_build/output/1do3_crates_turbopack-tests_tests_snapshot_basic_async_chunk_build_input_1a38y3r._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk_build/output/1do3_crates_turbopack-tests_tests_snapshot_basic_async_chunk_build_input_1a38y3r._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/async_chunk_build/output/index.entry.js (modified, +1/-1)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/chunk_loading_global/output/0_9x_turbopack-tests_tests_snapshot_basic_chunk_loading_global_input_index_0hi3tgp.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/chunk_loading_global/output/0_9x_turbopack-tests_tests_snapshot_basic_chunk_loading_global_input_index_0hi3tgp.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/chunk_loading_global/output/0_9x_turbopack-tests_tests_snapshot_basic_chunk_loading_global_input_index_176tecx.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/chunk_loading_global/output/0fw._turbopack-tests_tests_snapshot_basic_chunk_loading_global_input_index_0bkyka9.js (removed, +0/-5)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/chunk_loading_global/output/0rv8_turbopack-tests_tests_snapshot_basic_chunk_loading_global_input_index_176tecx.js (added, +5/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/chunked/output/1do3_crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_14uir__.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/chunked/output/1i9t_crates_turbopack-tests_tests_snapshot_basic_chunked_input_index_14uir__.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/chunked/output/turbopack_crates_turbopack-tests_tests_snapshot_basic_chunked_input_1_yzgm1._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/chunked/output/turbopack_crates_turbopack-tests_tests_snapshot_basic_chunked_input_1_yzgm1._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/ecmascript_minify/output/0_9x_turbopack-tests_tests_snapshot_basic_ecmascript_minify_input_index_103o_dh.js (renamed, +1/-1)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/ecmascript_minify/output/0_9x_turbopack-tests_tests_snapshot_basic_ecmascript_minify_input_index_103o_dh.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/ecmascript_minify/output/index.entry.js (modified, +1/-1)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/shebang/output/1do3_crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_0z_jazh.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/shebang/output/1i9t_crates_turbopack-tests_tests_snapshot_basic_shebang_input_index_0z_jazh.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/shebang/output/turbopack_crates_turbopack-tests_tests_snapshot_basic_shebang_input_02e38zh._.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/shebang/output/turbopack_crates_turbopack-tests_tests_snapshot_basic_shebang_input_02e38zh._.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/top-level-await/output/0_9x_turbopack-tests_tests_snapshot_basic_top-level-await_input_UserAPI_0c6krug.js (renamed, +2/-2)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/top-level-await/output/0_9x_turbopack-tests_tests_snapshot_basic_top-level-await_input_UserAPI_0c6krug.js.map (renamed, +0/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/top-level-await/output/0v.~_crates_turbopack-tests_tests_snapshot_basic_top-level-await_input_index_13urqno.js (removed, +0/-5)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/top-level-await/output/1do3_crates_turbopack-tests_tests_snapshot_basic_top-level-await_input_0zs_dr_._.js (renamed, +2/-2)

Code Example

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Pro
  Available memory (MB): 24284
  Available CPU cores: 12
Binaries:
  Node: 24.14.0
  npm: 11.9.0
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 16.2.0
  eslint-config-next: 16.2.0
  react: 19.2.4
  react-dom: 19.2.4
  typescript: 5.9.3
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://codesandbox.io/p/devbox/eager-shirley-333t5w

To Reproduce

  1. Use Next.js version 16.2.0.
  2. Run a production build using Turbopack: next build.
  3. Deploy the application behind an Nginx server or a WAF (Web Application Firewall) with standard security hardening rules (e.g., block_common_exploits.conf).
  4. Attempt to load the application.
  5. The browser console shows 403 Forbidden errors for static CSS and JS chunks.

Current vs. Expected behavior

Comparison of generated filenames:

VersionFilename ExampleNaming StrategyStatus
16.1.7turbopack-01ca012029ca2e66.jsClean HexadecimalPASS
16.2.0turbopack-0c3o1svijj_~~.jsReserved (~~)FAIL (403)
16.2.00...f7~att2_2.jsReserved (... and ~)FAIL (403)
16.2.00q~2copru0zy0.cssReserved (~)FAIL (403)

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Pro
  Available memory (MB): 24284
  Available CPU cores: 12
Binaries:
  Node: 24.14.0
  npm: 11.9.0
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 16.2.0
  eslint-config-next: 16.2.0
  react: 19.2.4
  react-dom: 19.2.4
  typescript: 5.9.3

Which area(s) are affected? (Select all that apply)

Turbopack

Which stage(s) are affected? (Select all that apply)

Other (Deployed)

Additional context

No response

extent analysis

Fix Plan

To resolve the 403 Forbidden errors for static CSS and JS chunks, we need to update the next.config.js file to use a custom naming strategy for Turbopack chunks.

Step-by-Step Solution

  1. Update next.config.js:
    module.exports = {
      //... other configurations ...
      experimental: {
        turbopack: true,
        // Add a custom naming strategy
        turbopackChunkExtension: (chunk) => {
          if (chunk.type === 'style') return '.css';
          return '.js';
        },
        turbopackChunkFilename: (chunk) => {
          const hash = require('crypto').createHash('sha256');
          hash.update(chunk.content);
          const filename = hash.digest('hex').slice(0, 8);
          if (chunk.type === 'style') return `styles-${filename}.css`;
          return `script-${filename}.js`;
        },
      },
    };
  2. Run a new production build:
    next build
  3. Redeploy the application.

Verification

After applying the fix, verify that the browser console no longer shows 403 Forbidden errors for static CSS and JS chunks. Check the network requests to ensure the chunk filenames are correctly generated without reserved characters.

Extra Tips

  • Ensure you are using the latest version of Next.js and Turbopack to avoid similar issues in the future.
  • Consider implementing a custom Web Application Firewall (WAF) rule to allow the new chunk filenames.
  • If you are using a Content Delivery Network (CDN), make sure to invalidate the cache after redeploying the application.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING