nextjs - ✅(Solved) Fix Static export: segment cache files are written to nested directories on Windows due to unnormalized backslashes [1 pull requests, 1 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#92339Fetched 2026-04-08 02:43:21
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
0
Participants
Timeline (top)
cross-referenced ×1issue_type_added ×1labeled ×1subscribed ×1

Fix Action

Fixed

PR fix notes

PR #92340: fix: normalize segment paths to forward slashes on Windows in static export

Description (problem / solution / changelog)

On Windows, path.relative() returns backslash-separated paths. These were passed as-is to convertSegmentPathToStaticExportFilename, which only replaced forward slashes with dots. As a result, the backslashes survived into the filename and were interpreted as directory separators when writing the output file, producing nested directories instead of flat __next.*.txt files.

This caused all RSC segment prefetch requests to 404 when serving a static export built on Windows.

Fix by making convertSegmentPathToStaticExportFilename replace both forward slashes and backslashes with dots.

What?

Changes the regex in convertSegmentPathToStaticExportFilename (packages/next/src/shared/lib/segment-cache/segment-value-encoding.ts) from /\//g to /[/\\]/g, so both forward slashes and backslashes are replaced with dots.

Why?

When building with output: 'export' on Windows, segment cache files (e.g. __next.foo.bar.__PAGE__.txt) were written into nested subdirectories instead of as flat files in the route directory. For example, a file that should be written as out/foo/bar/__next.foo.bar.__PAGE__.txt was instead created at out/foo/bar/__next.foo/bar/__PAGE__.txt. This made all RSC prefetch requests return 404 at runtime.

How?

path.relative() is platform-sensitive and returns backslash-separated paths on Windows. Fixing the regex in convertSegmentPathToStaticExportFilename to handle both separators ensures correct behavior regardless of where the build is run.

Unit tests are added in test/unit/export-collect-segment-paths.test.ts covering:

  • forward-slash paths (POSIX)
  • backslash paths (Windows path.relative() output)
  • mixed separators
  • end-to-end filename generation

Fixes #92339

Changed files

  • packages/next/src/shared/lib/segment-cache/segment-value-encoding.ts (modified, +4/-1)
  • test/unit/export-collect-segment-paths.test.ts (added, +50/-0)

Code Example

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Pro
  Available memory (MB): 65434
  Available CPU cores: 16
Binaries:
  Node: 22.17.1
  npm: 10.9.2
  Yarn: 1.22.19
  pnpm: 9.9.0
Relevant Packages:
  next: 16.2.2 // Latest available version is detected (16.2.2).
  eslint-config-next: N/A
  react: 19.2.4
  react-dom: 19.2.4
  typescript: 5.7.2
Next.js Config:
  output: export

---

// packages/next/src/export/index.ts
results.push(
  path.relative(segmentsDirectory, path.join(directory, segmentFile.name))
);

// ...
const segmentPath = '/' + segmentFileSrc.slice(0, -RSC_SEGMENT_SUFFIX.length);
const segmentFilename =
  convertSegmentPathToStaticExportFilename(segmentPath);

---

// packages/next/src/shared/lib/segment-cache/segment-value-encoding.ts
function convertSegmentPathToStaticExportFilename(segmentPath: string) {
  return `__next${segmentPath.replace(/\//g, '.')}.txt`;
}
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/yukiyokotani/nextjs-static-export-segment-404-reproduce

To Reproduce

Option A: View the live demo (no setup required)

The repository uses GitHub Actions on windows-latest to build and deploy to GitHub Pages. You can observe the bug directly in the browser:

  1. Visit https://yukiyokotani.github.io/nextjs-static-export-segment-404-reproduce/
  2. Open DevTools → Network tab
  3. Navigate to another page and back — RSC prefetch requests return 404
<img width="1391" height="709" alt="Image" src="https://github.com/user-attachments/assets/126d1d47-fcf4-4218-a1a6-e4ab1a8a2ff3" />

The deployed output (built on Windows) is available at: https://github.com/yukiyokotani/nextjs-static-export-segment-404-reproduce/tree/gh-pages

Option B: Reproduce locally on Windows

  1. Clone https://github.com/yukiyokotani/nextjs-static-export-segment-404-reproduce
  2. Run pnpm install
  3. Run next build on Windows
  4. Inspect out/foo/bar/ — segment files are written in nested subdirectories instead of flat files
  5. Serve the out/ directory and navigate to /foo/bar
  6. Open DevTools Network tab — RSC prefetch requests return 404

Current vs. Expected behavior

Current: On Windows, segment cache files are written as nested directories: out/foo/bar/__next.foo/bar/__PAGE__.txt

Expected: Segment cache files should be written as flat files with dot-separated names: out/foo/bar/__next.foo.bar.__PAGE__.txt

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Pro
  Available memory (MB): 65434
  Available CPU cores: 16
Binaries:
  Node: 22.17.1
  npm: 10.9.2
  Yarn: 1.22.19
  pnpm: 9.9.0
Relevant Packages:
  next: 16.2.2 // Latest available version is detected (16.2.2).
  eslint-config-next: N/A
  react: 19.2.4
  react-dom: 19.2.4
  typescript: 5.7.2
Next.js Config:
  output: export

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

Output

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

next build (local)

Additional context

When building a Next.js app with output: "export" on Windows, the RSC segment cache files are written with incorrect paths in the out/ directory, causing 404 errors when the client router requests them.

packages/next/src/export/index.ts uses path.relative() to compute the path of each .segment.rsc file and passes the result to convertSegmentPathToStaticExportFilename:

// packages/next/src/export/index.ts
results.push(
  path.relative(segmentsDirectory, path.join(directory, segmentFile.name))
);

// ...
const segmentPath = '/' + segmentFileSrc.slice(0, -RSC_SEGMENT_SUFFIX.length);
const segmentFilename =
  convertSegmentPathToStaticExportFilename(segmentPath);
// packages/next/src/shared/lib/segment-cache/segment-value-encoding.ts
function convertSegmentPathToStaticExportFilename(segmentPath: string) {
  return `__next${segmentPath.replace(/\//g, '.')}.txt`;
}

On Windows, path.relative() returns backslash-separated paths (e.g. foo\bar\__PAGE__.segment.rsc). The regex in convertSegmentPathToStaticExportFilename only replaces forward slashes, so backslashes remain.

When Node.js then writes the file using path.join(segmentsDirDest, segmentFilename), the backslashes are interpreted as directory separators, producing a nested directory structure.

extent analysis

TL;DR

The most likely fix is to modify the convertSegmentPathToStaticExportFilename function to handle backslashes correctly, ensuring that segment cache files are written as flat files with dot-separated names.

Guidance

  • Identify the root cause: The issue arises from path.relative() returning backslash-separated paths on Windows, which are not properly replaced by the regex in convertSegmentPathToStaticExportFilename.
  • Modify the convertSegmentPathToStaticExportFilename function to replace backslashes with dots, in addition to replacing forward slashes.
  • Verify the fix by checking the out/ directory for flat files with correct names after running next build.
  • Consider using a platform-agnostic method to handle path separators, such as using path.posix or a dedicated path manipulation library.

Example

// Modified convertSegmentPathToStaticExportFilename function
function convertSegmentPathToStaticExportFilename(segmentPath: string) {
  return `__next${segmentPath.replace(/\\/g, '.').replace(/\//g, '.')}.txt`;
}

Notes

This fix assumes that the issue is solely caused by the incorrect handling of backslashes in the convertSegmentPathToStaticExportFilename function. Additional testing and verification may be necessary to ensure that this fix resolves the issue entirely.

Recommendation

Apply the workaround by modifying the convertSegmentPathToStaticExportFilename function to correctly handle backslashes, as this is a targeted fix for the identified root cause.

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